mirror of
https://github.com/micropython/micropython.git
synced 2025-08-17 16:10:33 +02:00
Compare commits
19 Commits
v1.26.0
...
v1.22-rele
Author | SHA1 | Date | |
---|---|---|---|
|
8cd15829e2 | ||
|
ee3c9ccb54 | ||
|
e72d03855e | ||
|
02df2b09d4 | ||
|
e7ff724a87 | ||
|
cc7cfc7e8d | ||
|
b979c5a92a | ||
|
f53ee9f12b | ||
|
2531a15200 | ||
|
8b6e89a8ca | ||
|
a2e9ab362b | ||
|
1e8cc6c503 | ||
|
4c7d955a62 | ||
|
068aa28fc5 | ||
|
d5f3fcd935 | ||
|
9b8c64c9ce | ||
|
ac5e0b9f62 | ||
|
61b8361f5f | ||
|
4b4f6011e8 |
@@ -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
|
||||
|
||||
|
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@v4
|
||||
- name: Setup Biome
|
||||
uses: biomejs/setup-biome@v2
|
||||
with:
|
||||
version: 1.5.3
|
||||
- name: Run Biome
|
||||
run: biome ci --indent-style=space --indent-width=4 tests/ ports/webassembly
|
10
.github/workflows/code_formatting.yml
vendored
10
.github/workflows/code_formatting.yml
vendored
@@ -18,3 +18,13 @@ jobs:
|
||||
run: source tools/ci.sh && ci_c_code_formatting_run
|
||||
- name: Check code formatting
|
||||
run: git diff --exit-code
|
||||
|
||||
code-spelling:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_code_spell_setup
|
||||
- name: Run spell checker
|
||||
run: source tools/ci.sh && ci_code_spell_run
|
||||
|
9
.github/workflows/code_size.yml
vendored
9
.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,7 +18,7 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
|
2
.github/workflows/code_size_comment.yml
vendored
2
.github/workflows/code_size_comment.yml
vendored
@@ -11,7 +11,7 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: 'Download artifact'
|
||||
id: download-artifact
|
||||
|
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@v4
|
||||
# codespell version should be kept in sync with .pre-commit-config.yml
|
||||
- run: pip install --user codespell==2.4.1 tomli
|
||||
- run: codespell
|
||||
|
4
.github/workflows/commit_formatting.yml
vendored
4
.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 }}
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 100
|
||||
fetch-depth: '100'
|
||||
- uses: actions/setup-python@v5
|
||||
- name: Check commit message formatting
|
||||
run: source tools/ci.sh && ci_commit_formatting_run
|
||||
|
4
.github/workflows/docs.yml
vendored
4
.github/workflows/docs.yml
vendored
@@ -5,8 +5,6 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- docs/**
|
||||
- py/**
|
||||
- tests/cpydiff/**
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -21,7 +19,5 @@ jobs:
|
||||
- uses: actions/setup-python@v5
|
||||
- name: Install Python packages
|
||||
run: pip install -r docs/requirements.txt
|
||||
- name: Build unix port
|
||||
run: source tools/ci.sh && ci_unix_build_helper
|
||||
- name: Build docs
|
||||
run: make -C docs/ html
|
||||
|
2
.github/workflows/mpy_format.yml
vendored
2
.github/workflows/mpy_format.yml
vendored
@@ -15,7 +15,7 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-22.04 # use 22.04 to get python2
|
||||
runs-on: ubuntu-20.04 # use 20.04 to get python2
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
|
9
.github/workflows/ports_esp32.yml
vendored
9
.github/workflows/ports_esp32.yml
vendored
@@ -25,18 +25,17 @@ jobs:
|
||||
ci_func: # names are functions in ci.sh
|
||||
- esp32_build_cmod_spiram_s2
|
||||
- esp32_build_s3_c3
|
||||
- esp32_build_c2_c6
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- 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/
|
||||
|
7
.github/workflows/ports_mimxrt.yml
vendored
7
.github/workflows/ports_mimxrt.yml
vendored
@@ -19,14 +19,9 @@ 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@v4
|
||||
with:
|
||||
path: 'micropython repo'
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_mimxrt_setup
|
||||
- name: Build
|
||||
|
2
.github/workflows/ports_nrf.yml
vendored
2
.github/workflows/ports_nrf.yml
vendored
@@ -19,7 +19,7 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
|
@@ -1,4 +1,4 @@
|
||||
name: alif port
|
||||
name: qemu-arm port
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -11,23 +11,22 @@ on:
|
||||
- 'shared/**'
|
||||
- 'lib/**'
|
||||
- 'drivers/**'
|
||||
- 'ports/alif/**'
|
||||
- 'ports/qemu-arm/**'
|
||||
- 'tests/**'
|
||||
|
||||
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
|
||||
build_and_test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_alif_setup
|
||||
- name: Build ci_${{matrix.ci_func }}
|
||||
run: source tools/ci.sh && ci_${{ matrix.ci_func }}
|
||||
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
|
51
.github/workflows/ports_qemu.yml
vendored
51
.github/workflows/ports_qemu.yml
vendored
@@ -1,51 +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
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_qemu_setup_arm
|
||||
- name: Build and run test suite ci_qemu_build_arm_${{ matrix.ci_func }}
|
||||
run: source tools/ci.sh && ci_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@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_qemu_setup_rv32
|
||||
- name: Build and run test suite
|
||||
run: source tools/ci.sh && ci_qemu_build_rv32
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
2
.github/workflows/ports_renesas-ra.yml
vendored
2
.github/workflows/ports_renesas-ra.yml
vendored
@@ -19,7 +19,7 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build_renesas_ra_board:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
|
5
.github/workflows/ports_rp2.yml
vendored
5
.github/workflows/ports_rp2.yml
vendored
@@ -20,13 +20,8 @@ concurrency:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: 'micropython repo' # test build with space in path
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
path: 'micropython repo'
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_rp2_setup
|
||||
- name: Build
|
||||
|
3
.github/workflows/ports_stm32.yml
vendored
3
.github/workflows/ports_stm32.yml
vendored
@@ -25,8 +25,7 @@ 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@v4
|
||||
- name: Install packages
|
||||
|
132
.github/workflows/ports_unix.yml
vendored
132
.github/workflows/ports_unix.yml
vendored
@@ -71,11 +71,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
# Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests.
|
||||
# Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default.
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_unix_coverage_setup
|
||||
- name: Build
|
||||
@@ -93,17 +88,16 @@ jobs:
|
||||
(cd ports/unix && gcov -o build-coverage/py ../../py/*.c || true)
|
||||
(cd ports/unix && gcov -o build-coverage/extmod ../../extmod/*.c || true)
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@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@v4
|
||||
- name: Install packages
|
||||
@@ -121,7 +115,7 @@ jobs:
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
nanbox:
|
||||
runs-on: ubuntu-22.04 # use 22.04 to get python2, and libffi-dev:i386
|
||||
runs-on: ubuntu-20.04 # use 20.04 to get python2, and libffi-dev:i386
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
@@ -134,20 +128,6 @@ jobs:
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
longlong:
|
||||
runs-on: ubuntu-22.04 # use 22.04 to get python2, and libffi-dev:i386
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_unix_32bit_setup
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_longlong_build
|
||||
- name: Run main test suite
|
||||
run: source tools/ci.sh && ci_unix_longlong_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
float:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -160,20 +140,8 @@ jobs:
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
gil_enabled:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_gil_enabled_build
|
||||
- name: Run main test suite
|
||||
run: source tools/ci.sh && ci_unix_gil_enabled_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@v4
|
||||
- name: Install packages
|
||||
@@ -187,7 +155,7 @@ jobs:
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
float_clang:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
@@ -200,15 +168,22 @@ jobs:
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
settrace:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_settrace_build
|
||||
- name: Run main test suite
|
||||
run: source tools/ci.sh && ci_unix_settrace_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
settrace_stackless:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
# Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests.
|
||||
# Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default.
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_settrace_stackless_build
|
||||
- name: Run main test suite
|
||||
@@ -218,7 +193,7 @@ jobs:
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
macos:
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-11.0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
@@ -233,8 +208,7 @@ jobs:
|
||||
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@v4
|
||||
- name: Install packages
|
||||
@@ -248,8 +222,7 @@ jobs:
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
qemu_arm:
|
||||
# ubuntu-22.04 is needed for older libffi.
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
@@ -261,68 +234,3 @@ jobs:
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
qemu_riscv64:
|
||||
# ubuntu-22.04 is needed for older libffi.
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_unix_qemu_riscv64_setup
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_qemu_riscv64_build
|
||||
- name: Run main test suite
|
||||
run: source tools/ci.sh && ci_unix_qemu_riscv64_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
sanitize_address:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
# Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests.
|
||||
# Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default.
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_unix_coverage_setup
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_sanitize_address_build
|
||||
- name: Run main test suite
|
||||
run: source tools/ci.sh && ci_unix_sanitize_address_run_tests
|
||||
- name: Test merging .mpy files
|
||||
run: source tools/ci.sh && ci_unix_coverage_run_mpy_merge_tests
|
||||
- name: Build native mpy modules
|
||||
run: source tools/ci.sh && ci_native_mpy_modules_build
|
||||
- name: Test importing .mpy generated by mpy_ld.py
|
||||
run: source tools/ci.sh && ci_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@v4
|
||||
- uses: actions/setup-python@v5
|
||||
# Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests.
|
||||
# Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default.
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_unix_coverage_setup
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_sanitize_undefined_build
|
||||
- name: Run main test suite
|
||||
run: source tools/ci.sh && ci_unix_sanitize_undefined_run_tests
|
||||
- name: Test merging .mpy files
|
||||
run: source tools/ci.sh && ci_unix_coverage_run_mpy_merge_tests
|
||||
- name: Build native mpy modules
|
||||
run: source tools/ci.sh && ci_native_mpy_modules_build
|
||||
- name: Test importing .mpy generated by mpy_ld.py
|
||||
run: source tools/ci.sh && ci_unix_coverage_run_native_mpy_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
124
.github/workflows/ports_windows.yml
vendored
124
.github/workflows/ports_windows.yml
vendored
@@ -18,129 +18,7 @@ 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)'
|
||||
- visualstudio: '2019'
|
||||
vs_version: '[16, 17)'
|
||||
- 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 2017
|
||||
if: matrix.visualstudio == '2017'
|
||||
run: |
|
||||
choco install visualstudio2017buildtools
|
||||
choco install visualstudio2017-workload-vctools
|
||||
choco install windows-sdk-8.1
|
||||
- name: Install Visual Studio 2019
|
||||
if: matrix.visualstudio == '2019'
|
||||
run: |
|
||||
choco install visualstudio2019buildtools
|
||||
choco install visualstudio2019-workload-vctools
|
||||
choco install windows-sdk-8.1
|
||||
- uses: microsoft/setup-msbuild@v2
|
||||
with:
|
||||
vs-version: ${{ matrix.vs_version }}
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build mpy-cross.exe
|
||||
run: msbuild mpy-cross\mpy-cross.vcxproj -maxcpucount -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }}
|
||||
- name: Update submodules
|
||||
run: git submodule update --init lib/micropython-lib
|
||||
- name: Build micropython.exe
|
||||
run: msbuild ports\windows\micropython.vcxproj -maxcpucount -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }} -property:PyVariant=${{ matrix.variant }}
|
||||
- name: Get micropython.exe path
|
||||
id: get_path
|
||||
run: |
|
||||
$exePath="$(msbuild ports\windows\micropython.vcxproj -nologo -v:m -t:ShowTargetPath -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }} -property:PyVariant=${{ matrix.variant }})"
|
||||
echo ("micropython=" + $exePath.Trim()) >> $env:GITHUB_OUTPUT
|
||||
- name: Run tests
|
||||
id: test
|
||||
env:
|
||||
MICROPY_MICROPYTHON: ${{ steps.get_path.outputs.micropython }}
|
||||
working-directory: tests
|
||||
run: python run-tests.py
|
||||
- name: Print failures
|
||||
if: failure() && steps.test.conclusion == 'failure'
|
||||
working-directory: tests
|
||||
run: python run-tests.py --print-failures
|
||||
- name: Run mpy tests
|
||||
id: test_mpy
|
||||
env:
|
||||
MICROPY_MICROPYTHON: ${{ steps.get_path.outputs.micropython }}
|
||||
working-directory: tests
|
||||
run: python run-tests.py --via-mpy -d basics float micropython
|
||||
- name: Print mpy failures
|
||||
if: failure() && steps.test_mpy.conclusion == 'failure'
|
||||
working-directory: tests
|
||||
run: python run-tests.py --print-failures
|
||||
|
||||
build-mingw:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
variant: [dev, standard]
|
||||
sys: [mingw32, mingw64]
|
||||
include:
|
||||
- sys: mingw32
|
||||
env: i686
|
||||
- sys: mingw64
|
||||
env: x86_64
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
CHERE_INVOKING: enabled_from_arguments
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/setup-python@v5
|
||||
# note: can go back to installing mingw-w64-${{ matrix.env }}-python after
|
||||
# MSYS2 updates to Python >3.12 (due to settrace compatibility issue)
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.sys }}
|
||||
update: true
|
||||
install: >-
|
||||
make
|
||||
mingw-w64-${{ matrix.env }}-gcc
|
||||
pkg-config
|
||||
git
|
||||
diffutils
|
||||
path-type: inherit # Remove when setup-python is removed
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build mpy-cross.exe
|
||||
run: make -C mpy-cross -j2
|
||||
- name: Update submodules
|
||||
run: make -C ports/windows VARIANT=${{ matrix.variant }} submodules
|
||||
- name: Build micropython.exe
|
||||
run: make -C ports/windows -j2 VARIANT=${{ matrix.variant }}
|
||||
- name: Run tests
|
||||
id: test
|
||||
run: make -C ports/windows test_full VARIANT=${{ matrix.variant }}
|
||||
- name: Print failures
|
||||
if: failure() && steps.test.conclusion == 'failure'
|
||||
working-directory: tests
|
||||
run: python run-tests.py --print-failures
|
||||
|
||||
cross-build-on-linux:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
31
.github/workflows/ports_zephyr.yml
vendored
31
.github/workflows/ports_zephyr.yml
vendored
@@ -20,41 +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: false
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: false
|
||||
docker-images: false
|
||||
swap-storage: false
|
||||
- uses: actions/checkout@v4
|
||||
- id: versions
|
||||
name: Read Zephyr version
|
||||
run: source tools/ci.sh && echo "ZEPHYR=$ZEPHYR_VERSION" | tee "$GITHUB_OUTPUT"
|
||||
- name: Cached Zephyr Workspace
|
||||
id: cache_workspace
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
# note that the Zephyr CI docker image is 15GB. At time of writing
|
||||
# GitHub caches are limited to 10GB total for a project. So we only
|
||||
# cache the "workspace"
|
||||
path: ./zephyrproject
|
||||
key: zephyr-workspace-${{ steps.versions.outputs.ZEPHYR }}
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: zephyr
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_zephyr_setup
|
||||
- name: Install Zephyr
|
||||
if: steps.cache_workspace.outputs.cache-hit != 'true'
|
||||
run: source tools/ci.sh && ci_zephyr_install
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_zephyr_build
|
||||
- name: Run main test suite
|
||||
run: source tools/ci.sh && ci_zephyr_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
6
.github/workflows/ruff.yml
vendored
6
.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@v4
|
||||
# ruff version should be kept in sync with .pre-commit-config.yaml & also micropython-lib
|
||||
- run: pipx install ruff==0.11.6
|
||||
- run: pip install --user ruff==0.1.3
|
||||
- run: ruff check --output-format=github .
|
||||
- run: ruff format --diff .
|
||||
|
3
.gitignore
vendored
3
.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__/
|
||||
|
19
.gitmodules
vendored
19
.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
|
||||
@@ -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)
|
||||
|
10
README.md
10
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)
|
||||
@@ -108,13 +108,13 @@ track of the code size of the core runtime and VM.
|
||||
|
||||
In addition, the following ports are provided in this repository:
|
||||
- [cc3200](ports/cc3200) -- Texas Instruments CC3200 (including PyCom WiPy).
|
||||
- [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3, ESP32C6).
|
||||
- [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](ports/qemu) -- QEMU-based emulated target (for testing)
|
||||
- [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.
|
||||
|
11
docs/conf.py
11
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 ------------------------------------------------
|
||||
|
||||
@@ -71,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
|
||||
@@ -247,7 +244,7 @@ latex_documents = [
|
||||
master_doc,
|
||||
"MicroPython.tex",
|
||||
"MicroPython Documentation",
|
||||
micropy_authors,
|
||||
"Damien P. George, Paul Sokolovsky, and contributors",
|
||||
"manual",
|
||||
),
|
||||
]
|
||||
@@ -284,7 +281,7 @@ man_pages = [
|
||||
"index",
|
||||
"micropython",
|
||||
"MicroPython Documentation",
|
||||
[micropy_authors],
|
||||
["Damien P. George, Paul Sokolovsky, and contributors"],
|
||||
1,
|
||||
),
|
||||
]
|
||||
@@ -303,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) {
|
||||
|
@@ -112,7 +112,7 @@ Check that you have Python available on your system:
|
||||
.. code-block:: bash
|
||||
|
||||
$ python3
|
||||
Python 3.5.0 (default, Jul 17 2020, 14:04:10)
|
||||
Python 3.5.0 (default, Jul 17 2020, 14:04:10)
|
||||
[GCC 5.4.0 20160609] on linux
|
||||
Type "help", "copyright", "credits" or "license" for more information.
|
||||
>>>
|
||||
@@ -278,7 +278,7 @@ To run a selection of tests on a board/device connected over USB use:
|
||||
.. code-block:: bash
|
||||
|
||||
$ cd tests
|
||||
$ ./run-tests.py -t /dev/ttyACM0
|
||||
$ ./run-tests.py --target minimal --device /dev/ttyACM0
|
||||
|
||||
See also :ref:`writingtests`.
|
||||
|
||||
|
@@ -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.
|
||||
|
||||
|
@@ -83,7 +83,7 @@ The basic MicroPython firmware is implemented in the main port file, e.g ``main.
|
||||
}
|
||||
|
||||
// There is no filesystem so opening a file raises an exception.
|
||||
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
|
||||
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
|
||||
mp_raise_OSError(MP_ENOENT);
|
||||
}
|
||||
|
||||
@@ -262,17 +262,17 @@ To add a custom module like ``myport``, first add the module definition in a fil
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
static mp_obj_t myport_info(void) {
|
||||
STATIC mp_obj_t myport_info(void) {
|
||||
mp_printf(&mp_plat_print, "info about my port\n");
|
||||
return mp_const_none;
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_0(myport_info_obj, myport_info);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(myport_info_obj, myport_info);
|
||||
|
||||
static const mp_rom_map_elem_t myport_module_globals_table[] = {
|
||||
STATIC const mp_rom_map_elem_t myport_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_myport) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&myport_info_obj) },
|
||||
};
|
||||
static MP_DEFINE_CONST_DICT(myport_module_globals, myport_module_globals_table);
|
||||
STATIC MP_DEFINE_CONST_DICT(myport_module_globals, myport_module_globals_table);
|
||||
|
||||
const mp_obj_module_t myport_module = {
|
||||
.base = { &mp_type_module },
|
||||
|
@@ -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,8 +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.
|
||||
The period is in milliseconds.
|
||||
|
||||
Virtual timers are not currently supported on this port.
|
||||
|
||||
@@ -387,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
|
||||
@@ -397,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%)
|
||||
@@ -406,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
|
||||
@@ -544,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
|
||||
----------------
|
||||
@@ -728,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)
|
||||
@@ -814,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
|
||||
---
|
||||
@@ -838,9 +674,6 @@ The RMT is ESP32-specific and allows generation of accurate digital pulses with
|
||||
# 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
|
||||
--------------
|
||||
|
||||
@@ -907,33 +740,20 @@ 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.
|
||||
@@ -163,10 +163,10 @@ sys.stdin.read() if it's needed to read characters from the UART(0)
|
||||
while it's also used for the REPL (or detach, read, then reattach).
|
||||
When detached the UART(0) can be used for other purposes.
|
||||
|
||||
If there are no objects in any of the dupterm slots when the REPL is started (on
|
||||
: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::
|
||||
@@ -284,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)
|
||||
|
||||
|
@@ -18,31 +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:: gpio_deep_sleep_hold(enable)
|
||||
|
||||
Configure whether non-RTC GPIO pin configuration is retained during
|
||||
@@ -88,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
|
||||
----------------
|
||||
@@ -145,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()
|
||||
|
||||
@@ -195,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
|
||||
|
@@ -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,13 +164,11 @@ Configuration
|
||||
wait forever. The timeout can also be provided as arg to
|
||||
`recv()`/`irecv()`/`recvinto()`.
|
||||
|
||||
*rate*: (ESP32 only) Set the transmission speed for
|
||||
*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/v5.2.3/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.
|
||||
<https://docs.espressif.com/projects/esp-idf/en/v4.4.1/esp32/
|
||||
api-reference/network/esp_wifi.html#_CPPv415wifi_phy_rate_t>`_.
|
||||
|
||||
.. data:: Returns:
|
||||
|
||||
@@ -184,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
|
||||
|
||||
@@ -443,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
|
||||
@@ -474,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)
|
||||
@@ -595,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
|
||||
|
||||
@@ -652,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)
|
||||
@@ -754,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:
|
||||
@@ -839,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,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_READ`` 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_READ``, ``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
|
||||
``````
|
||||
|
@@ -71,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``.
|
||||
|
@@ -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
|
@@ -62,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()
|
||||
|
||||
@@ -126,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])
|
||||
@@ -264,13 +259,9 @@ Classes
|
||||
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.
|
||||
|
@@ -43,8 +43,7 @@ Constructors
|
||||
- *pin* is a machine.Pin instance.
|
||||
- *n* is the number of LEDs in the strip.
|
||||
- *bpp* is 3 for RGB LEDs, and 4 for RGBW LEDs.
|
||||
- *timing* is 0 for 400KHz, and 1 for 800kHz LEDs (most are 800kHz). You
|
||||
may also supply a timing tuple as accepted by `machine.bitstream()`.
|
||||
- *timing* is 0 for 400KHz, and 1 for 800kHz LEDs (most are 800kHz).
|
||||
|
||||
Pixel access methods
|
||||
--------------------
|
||||
|
@@ -6,11 +6,11 @@ class LAN -- control an Ethernet module
|
||||
|
||||
This class allows you to control the Ethernet interface. The PHY hardware type is board-specific.
|
||||
|
||||
Example usage, for a board with built-in LAN support::
|
||||
Example usage::
|
||||
|
||||
import network
|
||||
nic = network.LAN(0)
|
||||
print(nic.ipconfig("addr4"))
|
||||
print(nic.ifconfig())
|
||||
|
||||
# now use socket as usual
|
||||
...
|
||||
@@ -32,7 +32,7 @@ Constructors
|
||||
- *phy_addr* specifies the address of the PHY interface. As with *phy_type*, the hardwired value has
|
||||
to be used for most boards and that value is the default.
|
||||
- *ref_clk_mode* specifies, whether the data clock is provided by the Ethernet controller or
|
||||
the PHY interface.
|
||||
the PYH interface.
|
||||
The default value is the one that matches the board. If set to ``LAN.OUT`` or ``Pin.OUT``
|
||||
or ``True``, the clock is driven by the Ethernet controller, if set to ``LAN.IN``
|
||||
or ``Pin.IN`` or ``False``, the clock is driven by the PHY interface.
|
||||
@@ -41,9 +41,6 @@ Constructors
|
||||
|
||||
nic = LAN(0, phy_type=LAN.PHY_LAN8720, phy_addr=1, ref_clk_mode=Pin.IN)
|
||||
|
||||
.. note:: On esp32 port the constructor requires different arguments. See
|
||||
:ref:`esp32 port reference <esp32_network_lan>`.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
|
@@ -1,106 +0,0 @@
|
||||
.. currentmodule:: network
|
||||
.. _network.PPP:
|
||||
|
||||
class PPP -- create network connections over serial PPP
|
||||
=======================================================
|
||||
|
||||
This class allows you to create a network connection over a serial port using
|
||||
the PPP protocol.
|
||||
|
||||
.. note:: Currently only the esp32 port has PPP support enabled in the default
|
||||
firmware build. PPP support can be enabled in custom builds of the
|
||||
stm32 and rp2 ports by enabling networking support and setting
|
||||
``MICROPY_PY_NETWORK_PPP_LWIP`` to 1.
|
||||
|
||||
Example usage::
|
||||
|
||||
import network
|
||||
|
||||
ppp = network.PPP(uart)
|
||||
ppp.connect()
|
||||
|
||||
while not ppp.isconnected():
|
||||
pass
|
||||
|
||||
print(ppp.ipconfig("addr4"))
|
||||
|
||||
# use the socket module as usual, etc
|
||||
|
||||
ppp.disconnect()
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: PPP(stream)
|
||||
|
||||
Create a PPP driver object.
|
||||
|
||||
Arguments are:
|
||||
|
||||
- *stream* is any object that supports the stream protocol, but is most commonly a
|
||||
:class:`machine.UART` instance. This stream object must have an ``irq()`` method
|
||||
and an ``IRQ_RXIDLE`` constant, for use by `PPP.connect`.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: PPP.connect(security=SEC_NONE, user=None, key=None)
|
||||
|
||||
Initiate a PPP connection with the given parameters:
|
||||
|
||||
- *security* is the type of security, either ``PPP.SEC_NONE``, ``PPP.SEC_PAP``,
|
||||
or ``PPP.SEC_CHAP``.
|
||||
- *user* is an optional user name to use with the security mode.
|
||||
- *key* is an optional password to use with the security mode.
|
||||
|
||||
When this method is called the underlying stream has its interrupt configured to call
|
||||
`PPP.poll` via ``stream.irq(ppp.poll, stream.IRQ_RXIDLE)``. This makes sure the
|
||||
stream is polled, and data passed up the PPP stack, wheverver data becomes available
|
||||
on the stream.
|
||||
|
||||
The connection proceeds asynchronously, in the background.
|
||||
|
||||
.. method:: PPP.disconnect()
|
||||
|
||||
Terminate the connection. This must be called to cleanly close the PPP connection.
|
||||
|
||||
.. method:: PPP.isconnected()
|
||||
|
||||
Returns ``True`` if the PPP link is connected and up.
|
||||
Returns ``False`` otherwise.
|
||||
|
||||
.. method:: PPP.status()
|
||||
|
||||
Returns the PPP status.
|
||||
|
||||
.. method:: PPP.config(config_parameters)
|
||||
|
||||
Sets or gets parameters of the PPP interface. The only parameter that can be
|
||||
retrieved and set is the underlying stream, using::
|
||||
|
||||
stream = PPP.config("stream")
|
||||
PPP.config(stream=stream)
|
||||
|
||||
.. method:: PPP.ipconfig('param')
|
||||
PPP.ipconfig(param=value, ...)
|
||||
|
||||
See `AbstractNIC.ipconfig`.
|
||||
|
||||
.. method:: PPP.ifconfig([(ip, subnet, gateway, dns)])
|
||||
|
||||
See `AbstractNIC.ifconfig`.
|
||||
|
||||
.. method:: PPP.poll()
|
||||
|
||||
Poll the underlying stream for data, and pass it up the PPP stack.
|
||||
This is called automatically if the stream is a UART with a RXIDLE interrupt,
|
||||
so it's not usually necessary to call it manually.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: PPP.SEC_NONE
|
||||
PPP.SEC_PAP
|
||||
PPP.SEC_CHAP
|
||||
|
||||
The type of connection security.
|
@@ -9,14 +9,11 @@ the W5200 and W5500 chipsets. The particular chipset that is supported
|
||||
by the firmware is selected at compile-time via the MICROPY_PY_NETWORK_WIZNET5K
|
||||
option.
|
||||
|
||||
.. note:: The esp32 port also supports WIZnet W5500 chipsets, but this port
|
||||
uses the :ref:`network.LAN interface <esp32_spi_ethernet>`.
|
||||
|
||||
Example usage::
|
||||
|
||||
import network
|
||||
nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4)
|
||||
print(nic.ipconfig("addr4"))
|
||||
print(nic.ifconfig())
|
||||
|
||||
# now use socket as usual
|
||||
...
|
||||
@@ -54,7 +51,20 @@ Constructors
|
||||
Methods
|
||||
-------
|
||||
|
||||
This class implements most methods from `AbstractNIC <AbstractNIC>`, which are documented there. Additional methods are:
|
||||
.. method:: WIZNET5K.isconnected()
|
||||
|
||||
Returns ``True`` if the physical Ethernet link is connected and up.
|
||||
Returns ``False`` otherwise.
|
||||
|
||||
.. method:: WIZNET5K.ifconfig([(ip, subnet, gateway, dns)])
|
||||
|
||||
Get/set IP address, subnet mask, gateway and DNS.
|
||||
|
||||
When called with no arguments, this method returns a 4-tuple with the above information.
|
||||
|
||||
To set the above values, pass a 4-tuple with the required information. For example::
|
||||
|
||||
nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
|
||||
|
||||
.. method:: WIZNET5K.regs()
|
||||
|
||||
|
@@ -8,7 +8,7 @@ This class provides a driver for WiFi network processors. Example usage::
|
||||
|
||||
import network
|
||||
# enable station interface and connect to WiFi access point
|
||||
nic = network.WLAN(network.WLAN.IF_STA)
|
||||
nic = network.WLAN(network.STA_IF)
|
||||
nic.active(True)
|
||||
nic.connect('your-ssid', 'your-key')
|
||||
# now use sockets as usual
|
||||
@@ -18,8 +18,8 @@ Constructors
|
||||
.. class:: WLAN(interface_id)
|
||||
|
||||
Create a WLAN network interface object. Supported interfaces are
|
||||
``network.WLAN.IF_STA`` (station aka client, connects to upstream WiFi access
|
||||
points) and ``network.WLAN.IF_AP`` (access point, allows other WiFi clients to
|
||||
``network.STA_IF`` (station aka client, connects to upstream WiFi access
|
||||
points) and ``network.AP_IF`` (access point, allows other WiFi clients to
|
||||
connect). Availability of the methods below depends on interface type.
|
||||
For example, only STA interface may `WLAN.connect()` to an access point.
|
||||
|
||||
@@ -75,7 +75,7 @@ Methods
|
||||
Return the current status of the wireless connection.
|
||||
|
||||
When called with no argument the return value describes the network link status.
|
||||
The possible statuses are defined as constants in the :mod:`network` module:
|
||||
The possible statuses are defined as constants:
|
||||
|
||||
* ``STAT_IDLE`` -- no connection and no activity,
|
||||
* ``STAT_CONNECTING`` -- connecting in progress,
|
||||
@@ -85,18 +85,7 @@ Methods
|
||||
* ``STAT_GOT_IP`` -- connection successful.
|
||||
|
||||
When called with one argument *param* should be a string naming the status
|
||||
parameter to retrieve, and different parameters are supported depending on the
|
||||
mode the WiFi is in.
|
||||
|
||||
In STA mode, passing ``'rssi'`` returns a signal strength indicator value, whose
|
||||
format varies depending on the port (this is available on all ports that support
|
||||
WiFi network interfaces, except for CC3200).
|
||||
|
||||
In AP mode, passing ``'stations'`` returns a list of connected WiFi stations
|
||||
(this is available on all ports that support WiFi network interfaces, except for
|
||||
CC3200). The format of the station information entries varies across ports,
|
||||
providing either the raw BSSID of the connected station, the IP address of the
|
||||
connected station, or both.
|
||||
parameter to retrieve. Supported parameters in WiFI STA mode are: ``'rssi'``.
|
||||
|
||||
.. method:: WLAN.isconnected()
|
||||
|
||||
@@ -118,7 +107,7 @@ Methods
|
||||
|
||||
Get or set general network interface parameters. These methods allow to work
|
||||
with additional parameters beyond standard IP configuration (as dealt with by
|
||||
`AbstractNIC.ipconfig()`). These include network-specific and hardware-specific
|
||||
`WLAN.ifconfig()`). These include network-specific and hardware-specific
|
||||
parameters. For setting parameters, keyword argument syntax should be used,
|
||||
multiple parameters can be set at once. For querying, parameters name should
|
||||
be quoted as a string, and only one parameter can be queries at time::
|
||||
@@ -137,7 +126,7 @@ Methods
|
||||
============= ===========
|
||||
mac MAC address (bytes)
|
||||
ssid WiFi access point name (string)
|
||||
channel WiFi channel (integer). Depending on the port this may only be supported on the AP interface.
|
||||
channel WiFi channel (integer)
|
||||
hidden Whether SSID is hidden (boolean)
|
||||
security Security protocol supported (enumeration, see module constants)
|
||||
key Access key (string)
|
||||
|
@@ -20,7 +20,7 @@ This class provides a driver for the WiFi network processor in the WiPy. Example
|
||||
wlan.connect('your-ssid', auth=(WLAN.WPA2, 'your-key'))
|
||||
while not wlan.isconnected():
|
||||
time.sleep_ms(50)
|
||||
print(wlan.ipconfig("addr4"))
|
||||
print(wlan.ifconfig())
|
||||
|
||||
# now use socket as usual
|
||||
...
|
||||
@@ -96,10 +96,16 @@ Methods
|
||||
In case of STA mode, returns ``True`` if connected to a WiFi access point and has a valid IP address.
|
||||
In AP mode returns ``True`` when a station is connected, ``False`` otherwise.
|
||||
|
||||
.. method:: WLANWiPy.ipconfig('param')
|
||||
WLANWiPy.ipconfig(param=value, ...)
|
||||
.. method:: WLANWiPy.ifconfig(if_id=0, config=['dhcp' or configtuple])
|
||||
|
||||
See :meth:`AbstractNIC.ipconfig <AbstractNIC.ipconfig>`. Supported parameters are: ``dhcp4``, ``addr4``, ``gw4``.
|
||||
With no parameters given returns a 4-tuple of *(ip, subnet_mask, gateway, DNS_server)*.
|
||||
|
||||
if ``'dhcp'`` is passed as a parameter then the DHCP client is enabled and the IP params
|
||||
are negotiated with the AP.
|
||||
|
||||
If the 4-tuple config is given then a static IP is configured. For instance::
|
||||
|
||||
wlan.ifconfig(config=('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
|
||||
|
||||
.. method:: WLANWiPy.mode([mode])
|
||||
|
||||
|
@@ -24,7 +24,7 @@ For example::
|
||||
print("Waiting for connection...")
|
||||
while not nic.isconnected():
|
||||
time.sleep(1)
|
||||
print(nic.ipconfig("addr4"))
|
||||
print(nic.ifconfig())
|
||||
|
||||
# now use socket as usual
|
||||
import socket
|
||||
@@ -113,48 +113,8 @@ parameter should be `id`.
|
||||
connected to the AP. The list contains tuples of the form
|
||||
(MAC, RSSI).
|
||||
|
||||
.. method:: AbstractNIC.ipconfig('param')
|
||||
AbstractNIC.ipconfig(param=value, ...)
|
||||
|
||||
Get or set interface-specific IP-configuration interface parameters.
|
||||
Supported parameters are the following (availability of a particular
|
||||
parameter depends on the port and the specific network interface):
|
||||
|
||||
* ``dhcp4`` (``True/False``) obtain an IPv4 address, gateway and dns
|
||||
server via DHCP. This method does not block and wait for an address
|
||||
to be obtained. To check if an address was obtained, use the read-only
|
||||
property ``has_dhcp4``.
|
||||
* ``gw4`` Get/set the IPv4 default-gateway.
|
||||
* ``dhcp6`` (``True/False``) obtain a DNS server via stateless DHCPv6.
|
||||
Obtaining IP Addresses via DHCPv6 is currently not implemented.
|
||||
* ``autoconf6`` (``True/False``) obtain a stateless IPv6 address via
|
||||
the network prefix shared in router advertisements. To check if a
|
||||
stateless address was obtained, use the read-only
|
||||
property ``has_autoconf6``.
|
||||
* ``addr4`` (e.g. ``192.168.0.4/24``) obtain the current IPv4 address
|
||||
and network mask as ``(ip, subnet)``-tuple, regardless of how this
|
||||
address was obtained. This method can be used to set a static IPv4
|
||||
address either as ``(ip, subnet)``-tuple or in CIDR-notation.
|
||||
* ``addr6`` (e.g. ``fe80::1234:5678``) obtain a list of current IPv6
|
||||
addresses as ``(ip, state, preferred_lifetime, valid_lifetime)``-tuple.
|
||||
This include link-local, slaac and static addresses.
|
||||
``preferred_lifetime`` and ``valid_lifetime`` represent the remaining
|
||||
valid and preferred lifetime of each IPv6 address, in seconds.
|
||||
``state`` indicates the current state of the address:
|
||||
|
||||
* ``0x08`` - ``0x0f`` indicates the address is tentative, counting the
|
||||
number of probes sent.
|
||||
* ``0x10`` The address is deprecated (but still valid)
|
||||
* ``0x30`` The address is preferred (and valid)
|
||||
* ``0x40`` The address is duplicated and can not be used.
|
||||
|
||||
This method can be used to set a static IPv6
|
||||
address, by setting this parameter to the address, like ``fe80::1234:5678``.
|
||||
|
||||
.. method:: AbstractNIC.ifconfig([(ip, subnet, gateway, dns)])
|
||||
|
||||
.. note:: This function is deprecated, use `ipconfig()` instead.
|
||||
|
||||
Get/set IP-level network interface parameters: IP address, subnet mask,
|
||||
gateway and DNS server. When called with no arguments, this method returns
|
||||
a 4-tuple with the above information. To set the above values, pass a
|
||||
@@ -167,7 +127,7 @@ parameter should be `id`.
|
||||
|
||||
Get or set general network interface parameters. These methods allow to work
|
||||
with additional parameters beyond standard IP configuration (as dealt with by
|
||||
`ipconfig()`). These include network-specific and hardware-specific
|
||||
`ifconfig()`). These include network-specific and hardware-specific
|
||||
parameters. For setting parameters, the keyword argument
|
||||
syntax should be used, and multiple parameters can be set at once. For
|
||||
querying, a parameter name should be quoted as a string, and only one
|
||||
@@ -192,7 +152,6 @@ provide a way to control networking interfaces of various kinds.
|
||||
network.WLANWiPy.rst
|
||||
network.WIZNET5K.rst
|
||||
network.LAN.rst
|
||||
network.PPP.rst
|
||||
|
||||
Network functions
|
||||
=================
|
||||
@@ -236,20 +195,6 @@ The following are functions available in the network module.
|
||||
|
||||
The default hostname is typically the name of the board.
|
||||
|
||||
.. function:: ipconfig('param')
|
||||
ipconfig(param=value, ...)
|
||||
|
||||
Get or set global IP-configuration parameters.
|
||||
Supported parameters are the following (availability of a particular
|
||||
parameter depends on the port and the specific network interface):
|
||||
|
||||
* ``dns`` Get/set DNS server. This method can support both, IPv4 and
|
||||
IPv6 addresses.
|
||||
* ``prefer`` (``4/6``) Specify which address type to return, if a domain
|
||||
name has both A and AAAA records. Note, that this does not clear the
|
||||
local DNS cache, so that any previously obtained addresses might not
|
||||
change.
|
||||
|
||||
.. function:: phy_mode([mode])
|
||||
|
||||
Get or set the PHY mode.
|
||||
|
@@ -1,115 +0,0 @@
|
||||
:mod:`openamp` -- provides standard Asymmetric Multiprocessing (AMP) support
|
||||
============================================================================
|
||||
|
||||
.. module:: openamp
|
||||
:synopsis: provides standard Asymmetric Multiprocessing (AMP) support
|
||||
|
||||
The ``openamp`` module provides a standard inter-processor communications infrastructure
|
||||
for MicroPython. The module handles all of the details of OpenAMP, such as setting up
|
||||
the shared resource table, initializing vrings, etc. It provides an API for using the
|
||||
RPMsg bus infrastructure with the `Endpoint` class, and provides processor Life Cycle
|
||||
Management (LCM) support, such as loading firmware and starting and stopping a remote
|
||||
core, via the `RemoteProc` class.
|
||||
|
||||
Example usage::
|
||||
|
||||
import openamp
|
||||
|
||||
def ept_recv_callback(src, data):
|
||||
print("Received message on endpoint", data)
|
||||
|
||||
# Create a new RPMsg endpoint to communicate with the remote core.
|
||||
ept = openamp.Endpoint("vuart-channel", callback=ept_recv_callback)
|
||||
|
||||
# Create a RemoteProc object, load its firmware and start it.
|
||||
rproc = openamp.RemoteProc("virtual_uart.elf") # Or entry point address (ex 0x081E0000)
|
||||
rproc.start()
|
||||
|
||||
while True:
|
||||
if ept.is_ready():
|
||||
ept.send("data")
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: new_service_callback(ns_callback)
|
||||
|
||||
Set the new service callback.
|
||||
|
||||
The *ns_callback* argument is a function that will be called when the remote processor
|
||||
announces new services. At that point the host processor can choose to create the
|
||||
announced endpoint, if this particular service is supported, or ignore it if it's
|
||||
not. If this function is not set, the host processor should first register the
|
||||
endpoint locally, and it will be automatically bound when the remote announces
|
||||
the service.
|
||||
|
||||
Endpoint class
|
||||
--------------
|
||||
|
||||
.. class:: Endpoint(name, callback, src=ENDPOINT_ADDR_ANY, dest=ENDPOINT_ADDR_ANY)
|
||||
|
||||
Construct a new RPMsg Endpoint. An endpoint is a bidirectional communication
|
||||
channel between two cores.
|
||||
|
||||
Arguments are:
|
||||
|
||||
- *name* is the name of the endpoint.
|
||||
- *callback* is a function that is called when the endpoint receives data with the
|
||||
source address of the remote point, and the data as bytes passed by reference.
|
||||
- *src* is the endpoint source address. If none is provided one will be assigned
|
||||
to the endpoint by the library.
|
||||
- *dest* is the endpoint destination address. If the endpoint is created from the
|
||||
new_service_callback, this must be provided and it must match the remote endpoint's
|
||||
source address. If the endpoint is registered locally, before the announcement, the
|
||||
destination address will be assigned by the library when the endpoint is bound.
|
||||
|
||||
.. method:: Endpoint.deinit()
|
||||
|
||||
Destroy the endpoint and release all of its resources.
|
||||
|
||||
.. method:: Endpoint.is_ready()
|
||||
|
||||
Returns True if the endpoint is ready to send (i.e., has both a source and destination addresses)
|
||||
|
||||
.. method:: Endpoint.send(src=-1, dest=-1, timeout=-1)
|
||||
|
||||
Send a message to the remote processor over this endpoint.
|
||||
|
||||
Arguments are:
|
||||
|
||||
- *src* is the source endpoint address of the message. If none is provided, the
|
||||
source address the endpoint is bound to is used.
|
||||
- *dest* is the destination endpoint address of the message. If none is provided,
|
||||
the destination address the endpoint is bound to is used.
|
||||
- *timeout* specifies the time in milliseconds to wait for a free buffer. By default
|
||||
the function is blocking.
|
||||
|
||||
RemoteProc class
|
||||
----------------
|
||||
|
||||
.. class:: RemoteProc(entry)
|
||||
|
||||
The RemoteProc object provides processor Life Cycle Management (LCM) support, such as
|
||||
loading firmware, starting and stopping a remote core.
|
||||
|
||||
The *entry* argument can be a path to firmware image, in which case the firmware is
|
||||
loaded from file to its target memory, or an entry point address, in which case the
|
||||
firmware must be loaded already at the given address.
|
||||
|
||||
.. method:: RemoteProc.start()
|
||||
|
||||
Starts the remote processor.
|
||||
|
||||
.. method:: RemoteProc.stop()
|
||||
|
||||
Stops the remote processor. The exact behavior is platform-dependent. On the STM32H7 for
|
||||
example it's not possible to stop and then restart the Cortex-M4 core, so a complete
|
||||
system reset is performed on a call to this function.
|
||||
|
||||
.. method:: RemoteProc.shutdown()
|
||||
|
||||
Shutdown stops the remote processor and releases all of its resources. The exact behavior
|
||||
is platform-dependent, however typically it disables power and clocks to the remote core.
|
||||
This function is also used as the finaliser (i.e., called when ``RemoteProc`` object is
|
||||
collected). Note that on the STM32H7, it's not possible to stop and then restart the
|
||||
Cortex-M4 core, so a complete system reset is performed on a call to this function.
|
@@ -136,30 +136,192 @@ Terminal redirection and duplication
|
||||
Filesystem mounting
|
||||
-------------------
|
||||
|
||||
The following functions and classes have been moved to the :mod:`vfs` module.
|
||||
They are provided in this module only for backwards compatibility and will be
|
||||
removed in version 2 of MicroPython.
|
||||
Some ports provide a Virtual Filesystem (VFS) and the ability to mount multiple
|
||||
"real" filesystems within this VFS. Filesystem objects can be mounted at either
|
||||
the root of the VFS, or at a subdirectory that lives in the root. This allows
|
||||
dynamic and flexible configuration of the filesystem that is seen by Python
|
||||
programs. Ports that have this functionality provide the :func:`mount` and
|
||||
:func:`umount` functions, and possibly various filesystem implementations
|
||||
represented by VFS classes.
|
||||
|
||||
.. function:: mount(fsobj, mount_point, *, readonly)
|
||||
|
||||
See `vfs.mount`.
|
||||
Mount the filesystem object *fsobj* at the location in the VFS given by the
|
||||
*mount_point* string. *fsobj* can be a a VFS object that has a ``mount()``
|
||||
method, or a block device. If it's a block device then the filesystem type
|
||||
is automatically detected (an exception is raised if no filesystem was
|
||||
recognised). *mount_point* may be ``'/'`` to mount *fsobj* at the root,
|
||||
or ``'/<name>'`` to mount it at a subdirectory under the root.
|
||||
|
||||
If *readonly* is ``True`` then the filesystem is mounted read-only.
|
||||
|
||||
During the mount process the method ``mount()`` is called on the filesystem
|
||||
object.
|
||||
|
||||
Will raise ``OSError(EPERM)`` if *mount_point* is already mounted.
|
||||
|
||||
.. function:: umount(mount_point)
|
||||
|
||||
See `vfs.umount`.
|
||||
Unmount a filesystem. *mount_point* can be a string naming the mount location,
|
||||
or a previously-mounted filesystem object. During the unmount process the
|
||||
method ``umount()`` is called on the filesystem object.
|
||||
|
||||
Will raise ``OSError(EINVAL)`` if *mount_point* is not found.
|
||||
|
||||
.. class:: VfsFat(block_dev)
|
||||
|
||||
See `vfs.VfsFat`.
|
||||
Create a filesystem object that uses the FAT filesystem format. Storage of
|
||||
the FAT filesystem is provided by *block_dev*.
|
||||
Objects created by this constructor can be mounted using :func:`mount`.
|
||||
|
||||
.. staticmethod:: mkfs(block_dev)
|
||||
|
||||
Build a FAT filesystem on *block_dev*.
|
||||
|
||||
.. class:: VfsLfs1(block_dev, readsize=32, progsize=32, lookahead=32)
|
||||
|
||||
See `vfs.VfsLfs1`.
|
||||
Create a filesystem object that uses the `littlefs v1 filesystem format`_.
|
||||
Storage of the littlefs filesystem is provided by *block_dev*, which must
|
||||
support the :ref:`extended interface <block-device-interface>`.
|
||||
Objects created by this constructor can be mounted using :func:`mount`.
|
||||
|
||||
See :ref:`filesystem` for more information.
|
||||
|
||||
.. staticmethod:: mkfs(block_dev, readsize=32, progsize=32, lookahead=32)
|
||||
|
||||
Build a Lfs1 filesystem on *block_dev*.
|
||||
|
||||
.. note:: There are reports of littlefs v1 failing in certain situations,
|
||||
for details see `littlefs issue 347`_.
|
||||
|
||||
.. class:: VfsLfs2(block_dev, readsize=32, progsize=32, lookahead=32, mtime=True)
|
||||
|
||||
See `vfs.VfsLfs2`.
|
||||
Create a filesystem object that uses the `littlefs v2 filesystem format`_.
|
||||
Storage of the littlefs filesystem is provided by *block_dev*, which must
|
||||
support the :ref:`extended interface <block-device-interface>`.
|
||||
Objects created by this constructor can be mounted using :func:`mount`.
|
||||
|
||||
.. class:: VfsPosix(root=None)
|
||||
The *mtime* argument enables modification timestamps for files, stored using
|
||||
littlefs attributes. This option can be disabled or enabled differently each
|
||||
mount time and timestamps will only be added or updated if *mtime* is enabled,
|
||||
otherwise the timestamps will remain untouched. Littlefs v2 filesystems without
|
||||
timestamps will work without reformatting and timestamps will be added
|
||||
transparently to existing files once they are opened for writing. When *mtime*
|
||||
is enabled `os.stat` on files without timestamps will return 0 for the timestamp.
|
||||
|
||||
See `vfs.VfsPosix`.
|
||||
See :ref:`filesystem` for more information.
|
||||
|
||||
.. staticmethod:: mkfs(block_dev, readsize=32, progsize=32, lookahead=32)
|
||||
|
||||
Build a Lfs2 filesystem on *block_dev*.
|
||||
|
||||
.. note:: There are reports of littlefs v2 failing in certain situations,
|
||||
for details see `littlefs issue 295`_.
|
||||
|
||||
.. _littlefs v1 filesystem format: https://github.com/ARMmbed/littlefs/tree/v1
|
||||
.. _littlefs v2 filesystem format: https://github.com/ARMmbed/littlefs
|
||||
.. _littlefs issue 295: https://github.com/ARMmbed/littlefs/issues/295
|
||||
.. _littlefs issue 347: https://github.com/ARMmbed/littlefs/issues/347
|
||||
|
||||
Block devices
|
||||
-------------
|
||||
|
||||
A block device is an object which implements the block protocol. This enables a
|
||||
device to support MicroPython filesystems. The physical hardware is represented
|
||||
by a user defined class. The :class:`AbstractBlockDev` class is a template for
|
||||
the design of such a class: MicroPython does not actually provide that class,
|
||||
but an actual block device class must implement the methods described below.
|
||||
|
||||
A concrete implementation of this class will usually allow access to the
|
||||
memory-like functionality of a piece of hardware (like flash memory). A block
|
||||
device can be formatted to any supported filesystem and mounted using ``os``
|
||||
methods.
|
||||
|
||||
See :ref:`filesystem` for example implementations of block devices using the
|
||||
two variants of the block protocol described below.
|
||||
|
||||
.. _block-device-interface:
|
||||
|
||||
Simple and extended interface
|
||||
.............................
|
||||
|
||||
There are two compatible signatures for the ``readblocks`` and ``writeblocks``
|
||||
methods (see below), in order to support a variety of use cases. A given block
|
||||
device may implement one form or the other, or both at the same time. The second
|
||||
form (with the offset parameter) is referred to as the "extended interface".
|
||||
|
||||
Some filesystems (such as littlefs) that require more control over write
|
||||
operations, for example writing to sub-block regions without erasing, may require
|
||||
that the block device supports the extended interface.
|
||||
|
||||
.. class:: AbstractBlockDev(...)
|
||||
|
||||
Construct a block device object. The parameters to the constructor are
|
||||
dependent on the specific block device.
|
||||
|
||||
.. method:: readblocks(block_num, buf)
|
||||
readblocks(block_num, buf, offset)
|
||||
|
||||
The first form reads aligned, multiples of blocks.
|
||||
Starting at the block given by the index *block_num*, read blocks from
|
||||
the device into *buf* (an array of bytes).
|
||||
The number of blocks to read is given by the length of *buf*,
|
||||
which will be a multiple of the block size.
|
||||
|
||||
The second form allows reading at arbitrary locations within a block,
|
||||
and arbitrary lengths.
|
||||
Starting at block index *block_num*, and byte offset within that block
|
||||
of *offset*, read bytes from the device into *buf* (an array of bytes).
|
||||
The number of bytes to read is given by the length of *buf*.
|
||||
|
||||
.. method:: writeblocks(block_num, buf)
|
||||
writeblocks(block_num, buf, offset)
|
||||
|
||||
The first form writes aligned, multiples of blocks, and requires that the
|
||||
blocks that are written to be first erased (if necessary) by this method.
|
||||
Starting at the block given by the index *block_num*, write blocks from
|
||||
*buf* (an array of bytes) to the device.
|
||||
The number of blocks to write is given by the length of *buf*,
|
||||
which will be a multiple of the block size.
|
||||
|
||||
The second form allows writing at arbitrary locations within a block,
|
||||
and arbitrary lengths. Only the bytes being written should be changed,
|
||||
and the caller of this method must ensure that the relevant blocks are
|
||||
erased via a prior ``ioctl`` call.
|
||||
Starting at block index *block_num*, and byte offset within that block
|
||||
of *offset*, write bytes from *buf* (an array of bytes) to the device.
|
||||
The number of bytes to write is given by the length of *buf*.
|
||||
|
||||
Note that implementations must never implicitly erase blocks if the offset
|
||||
argument is specified, even if it is zero.
|
||||
|
||||
.. method:: ioctl(op, arg)
|
||||
|
||||
Control the block device and query its parameters. The operation to
|
||||
perform is given by *op* which is one of the following integers:
|
||||
|
||||
- 1 -- initialise the device (*arg* is unused)
|
||||
- 2 -- shutdown the device (*arg* is unused)
|
||||
- 3 -- sync the device (*arg* is unused)
|
||||
- 4 -- get a count of the number of blocks, should return an integer
|
||||
(*arg* is unused)
|
||||
- 5 -- get the number of bytes in a block, should return an integer,
|
||||
or ``None`` in which case the default value of 512 is used
|
||||
(*arg* is unused)
|
||||
- 6 -- erase a block, *arg* is the block number to erase
|
||||
|
||||
As a minimum ``ioctl(4, ...)`` must be intercepted; for littlefs
|
||||
``ioctl(6, ...)`` must also be intercepted. The need for others is
|
||||
hardware dependent.
|
||||
|
||||
Prior to any call to ``writeblocks(block, ...)`` littlefs issues
|
||||
``ioctl(6, block)``. This enables a device driver to erase the block
|
||||
prior to a write if the hardware requires it. Alternatively a driver
|
||||
might intercept ``ioctl(6, block)`` and return 0 (success). In this case
|
||||
the driver assumes responsibility for detecting the need for erasure.
|
||||
|
||||
Unless otherwise stated ``ioctl(op, arg)`` can return ``None``.
|
||||
Consequently an implementation can ignore unused values of ``op``. Where
|
||||
``op`` is intercepted, the return value for operations 4 and 5 are as
|
||||
detailed above. Other operations should return 0 on success and non-zero
|
||||
for failure, with the value returned being an ``OSError`` errno code.
|
||||
|
@@ -67,17 +67,11 @@ Methods
|
||||
:meth:`~CAN.restart()` can be used to leave the bus-off state
|
||||
- *baudrate* if a baudrate other than 0 is provided, this function will try to automatically
|
||||
calculate the CAN nominal bit time (overriding *prescaler*, *bs1* and *bs2*) that satisfies
|
||||
both the *baudrate* (within .1%) and the desired *sample_point* (to the nearest 1%). For more precise
|
||||
control over the CAN timing, set the *prescaler*, *bs1* and *bs2* parameters directly.
|
||||
- *sample_point* specifies the position of the bit sample with respect to the whole nominal bit time,
|
||||
expressed as an integer percentage of the nominal bit time. The default *sample_point* is 75%.
|
||||
This parameter is ignored unless *baudrate* is set.
|
||||
both the baudrate and the desired *sample_point*.
|
||||
- *sample_point* given in a percentage of the nominal bit time, the *sample_point* specifies the position
|
||||
of the bit sample with respect to the whole nominal bit time. The default *sample_point* is 75%.
|
||||
- *num_filter_banks* for classic CAN, this is the number of banks that will be assigned to CAN(1),
|
||||
the rest of the 28 are assigned to CAN(2).
|
||||
|
||||
The remaining parameters are only present on boards with CAN FD support, and configure the optional CAN FD
|
||||
Bit Rate Switch (BRS) feature:
|
||||
|
||||
- *brs_prescaler* is the value by which the CAN FD input clock is divided to generate the
|
||||
data bit time quanta. The prescaler can be a value between 1 and 32 inclusive.
|
||||
- *brs_sjw* is the resynchronisation jump width in units of time quanta for data bits;
|
||||
@@ -88,11 +82,10 @@ Methods
|
||||
it can be a value between 1 and 16 inclusive
|
||||
- *brs_baudrate* if a baudrate other than 0 is provided, this function will try to automatically
|
||||
calculate the CAN data bit time (overriding *brs_prescaler*, *brs_bs1* and *brs_bs2*) that satisfies
|
||||
both the *brs_baudrate* (within .1%) and the desired *brs_sample_point* (to the nearest 1%). For more
|
||||
precise control over the BRS timing, set the *brs_prescaler*, *brs_bs1* and *brs_bs2* parameters directly.
|
||||
- *brs_sample_point* specifies the position of the bit sample with respect to the whole nominal bit time,
|
||||
expressed as an integer percentage of the nominal bit time. The default *brs_sample_point* is 75%.
|
||||
This parameter is ignored unless *brs_baudrate* is set.
|
||||
both the baudrate and the desired *brs_sample_point*.
|
||||
- *brs_sample_point* given in a percentage of the data bit time, the *brs_sample_point* specifies the position
|
||||
of the bit sample with respect to the whole data bit time. The default *brs_sample_point* is 75%.
|
||||
|
||||
|
||||
The time quanta tq is the basic unit of time for the CAN bus. tq is the CAN
|
||||
prescaler value divided by PCLK1 (the frequency of internal peripheral bus 1);
|
||||
|
@@ -43,7 +43,7 @@ Methods
|
||||
|
||||
These methods implement the simple and :ref:`extended
|
||||
<block-device-interface>` block protocol defined by
|
||||
:class:`vfs.AbstractBlockDev`.
|
||||
:class:`os.AbstractBlockDev`.
|
||||
|
||||
Hardware Note
|
||||
-------------
|
||||
|
@@ -163,7 +163,7 @@ Methods
|
||||
- ``callback`` - as per TimerChannel.callback()
|
||||
|
||||
- ``pin`` None (the default) or a Pin object. If specified (and not None)
|
||||
this will cause the alternate function of the indicated pin
|
||||
this will cause the alternate function of the the indicated pin
|
||||
to be configured for this timer channel. An error will be raised if
|
||||
the pin doesn't support any alternate functions for this timer channel.
|
||||
|
||||
|
@@ -147,10 +147,10 @@ Power related functions
|
||||
(internal oscillator) directly. The higher frequencies use the HSE to
|
||||
drive the PLL (phase locked loop), and then use the output of the PLL.
|
||||
|
||||
Note that if you change the frequency while the USB is enabled then the USB
|
||||
may become unreliable. It is best to change the frequency in :ref:`boot.py`,
|
||||
before the USB peripheral is started. Also note that sysclk frequencies below
|
||||
36MHz do not allow the USB to function correctly.
|
||||
Note that if you change the frequency while the USB is enabled then
|
||||
the USB may become unreliable. It is best to change the frequency
|
||||
in boot.py, before the USB peripheral is started. Also note that sysclk
|
||||
frequencies below 36MHz do not allow the USB to function correctly.
|
||||
|
||||
.. function:: wfi()
|
||||
|
||||
@@ -205,20 +205,19 @@ Miscellaneous functions
|
||||
|
||||
.. function:: main(filename)
|
||||
|
||||
Set the filename of the main script to run after :ref:`boot.py` is finished.
|
||||
If this function is not called then the default file :ref:`main.py` will be
|
||||
executed.
|
||||
Set the filename of the main script to run after boot.py is finished. If
|
||||
this function is not called then the default file main.py will be executed.
|
||||
|
||||
It only makes sense to call this function from within boot.py.
|
||||
|
||||
.. function:: mount(device, mountpoint, *, readonly=False, mkfs=False)
|
||||
|
||||
.. note:: This function is deprecated. Mounting and unmounting devices should
|
||||
be performed by :meth:`vfs.mount` and :meth:`vfs.umount` instead.
|
||||
be performed by :meth:`os.mount` and :meth:`os.umount` instead.
|
||||
|
||||
Mount a block device and make it available as part of the filesystem.
|
||||
``device`` must be an object that provides the block protocol. (The
|
||||
following is also deprecated. See :class:`vfs.AbstractBlockDev` for the
|
||||
following is also deprecated. See :class:`os.AbstractBlockDev` for the
|
||||
correct way to create a block device.)
|
||||
|
||||
- ``readblocks(self, blocknum, buf)``
|
||||
|
@@ -1,293 +0,0 @@
|
||||
.. currentmodule:: rp2
|
||||
.. _rp2.DMA:
|
||||
|
||||
class DMA -- access to the RP2040's DMA controller
|
||||
==================================================
|
||||
|
||||
The :class:`DMA` class offers access to the RP2040's Direct Memory Access (DMA)
|
||||
controller, providing the ability move data between memory blocks and/or IO registers. The DMA
|
||||
controller has its own, separate read and write bus master connections onto the bus fabric and
|
||||
each DMA channel can independently read data from one address and write it back to another
|
||||
address, optionally incrementing one or both pointers, allowing it to perform transfers on behalf
|
||||
of the processor while the processor carries out other tasks or enters a low power state. The
|
||||
RP2040's DMA controller has 12 independent DMA channels that can run concurrently. For full
|
||||
details of the RP2040's DMA system see section 2.5 of the `RP2040 Datasheet
|
||||
<https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf>`_.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
The simplest use of the DMA controller is to move data from one block of memory to another.
|
||||
This can be accomplished with the following code::
|
||||
|
||||
a = bytearray(32*1024)
|
||||
b = bytearray(32*1024)
|
||||
d = rp2.DMA()
|
||||
c = d.pack_ctrl() # Just use the default control value.
|
||||
# The count is in 'transfers', which defaults to four-byte words, so divide length by 4
|
||||
d.config(read=a, write=b, count=len(a)//4, ctrl=c, trigger=True)
|
||||
# Wait for completion
|
||||
while d.active():
|
||||
pass
|
||||
|
||||
Note that while this example sits in an idle loop while it waits for the transfer to complete,
|
||||
the program could just as well do some useful work in this time instead.
|
||||
|
||||
Another, perhaps more common use of the DMA controller is to transfer between memory and an IO
|
||||
peripheral. In this situation the address of the IO register does not change for each transfer but
|
||||
the memory address needs to be incremented. It is also necessary to control the pace of the
|
||||
transfer so as to not write data before it can be accepted by a peripheral or read it before the
|
||||
data is ready, and this can be controlled with the ``treq_sel`` field of the DMA channel's control
|
||||
register. The various fields of the control register for each DMA channel can be packed
|
||||
using the :meth:`DMA.pack_ctrl()` method and unpacked using the :meth:`DMA.unpack_ctrl()`
|
||||
static method. Code to transfer data from a byte array to the TX FIFO of a PIO state machine,
|
||||
one byte at a time, looks like this::
|
||||
|
||||
# pio_num is index of the PIO block being used, sm_num is the state machine in that block.
|
||||
# my_state_machine is an rp2.PIO() instance.
|
||||
DATA_REQUEST_INDEX = (pio_num << 3) + sm_num
|
||||
|
||||
src_data = bytearray(1024)
|
||||
d = rp2.DMA()
|
||||
|
||||
# Transfer bytes, rather than words, don't increment the write address and pace the transfer.
|
||||
c = d.pack_ctrl(size=0, inc_write=False, treq_sel=DATA_REQUEST_INDEX)
|
||||
|
||||
d.config(
|
||||
read=src_data,
|
||||
write=my_state_machine,
|
||||
count=len(src_data),
|
||||
ctrl=c,
|
||||
trigger=True
|
||||
)
|
||||
|
||||
Note that in this example the value given for the write address is just the PIO state machine to
|
||||
which we are sending the data. This works because PIO state machines present the buffer protocol,
|
||||
allowing direct access to their data FIFO registers.
|
||||
|
||||
Constructor
|
||||
-----------
|
||||
|
||||
.. class:: DMA()
|
||||
|
||||
Claim one of the DMA controller channels for exclusive use.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: DMA.config(read=None, write=None, count=None, ctrl=None, trigger=False)
|
||||
|
||||
Configure the DMA registers for the channel and optionally start the transfer.
|
||||
Parameters are:
|
||||
|
||||
- *read*: The address from which the DMA controller will start reading data or
|
||||
an object that will provide data to be read. It can be an integer or any
|
||||
object that supports the buffer protocol.
|
||||
- *write*: The address to which the DMA controller will start writing or an
|
||||
object into which data will be written. It can be an integer or any object
|
||||
that supports the buffer protocol.
|
||||
- *count*: The number of bus transfers that will execute before this channel
|
||||
stops. Note that this is the number of transfers, not the number of bytes.
|
||||
If the transfers are 2 or 4 bytes wide then the total amount of data moved
|
||||
(and thus the size of required buffer) needs to be multiplied accordingly.
|
||||
- *ctrl*: The value for the DMA control register. This is an integer value
|
||||
that is typically packed using the :meth:`DMA.pack_ctrl()`.
|
||||
- *trigger*: Optionally commence the transfer immediately.
|
||||
|
||||
.. method:: DMA.irq(handler=None, hard=False)
|
||||
|
||||
Returns the IRQ object for this DMA channel and optionally configures it.
|
||||
|
||||
.. method:: DMA.close()
|
||||
|
||||
Release the claim on the underlying DMA channel and free the interrupt
|
||||
handler. The :class:`DMA` object can not be used after this operation.
|
||||
|
||||
.. method:: DMA.pack_ctrl(default=None, **kwargs)
|
||||
|
||||
Pack the values provided in the keyword arguments into the named fields of a new control
|
||||
register value. Any field that is not provided will be set to a default value. The
|
||||
default will either be taken from the provided ``default`` value, or if that is not
|
||||
given, a default suitable for the current channel; setting this to the current value
|
||||
of the `DMA.ctrl` attribute provides an easy way to override a subset of the fields.
|
||||
|
||||
The keys for the keyword arguments can be any key returned by the :meth:`DMA.unpack_ctrl()`
|
||||
method. The writable values are:
|
||||
|
||||
- *enable*: ``bool`` Set to enable the channel (default: ``True``).
|
||||
|
||||
- *high_pri*: ``bool`` Make this channel's bus traffic high priority (default: ``False``).
|
||||
|
||||
- *size*: ``int`` Transfer size: 0=byte, 1=half word, 2=word (default: 2).
|
||||
|
||||
- *inc_read*: ``bool`` Increment the read address after each transfer (default: ``True``).
|
||||
|
||||
- *inc_write*: ``bool`` Increment the write address after each transfer (default: ``True``).
|
||||
|
||||
- *ring_size*: ``int`` If non-zero, only the bottom ``ring_size`` bits of one
|
||||
address register will change when an address is incremented, causing the
|
||||
address to wrap at the next ``1 << ring_size`` byte boundary. Which
|
||||
address is wrapped is controlled by the ``ring_sel`` flag. A zero value
|
||||
disables address wrapping.
|
||||
|
||||
- *ring_sel*: ``bool`` Set to ``False`` to have the ``ring_size`` apply to the read address
|
||||
or ``True`` to apply to the write address.
|
||||
|
||||
- *chain_to*: ``int`` The channel number for a channel to trigger after this transfer
|
||||
completes. Setting this value to this DMA object's own channel number
|
||||
disables chaining (this is the default).
|
||||
|
||||
- *treq_sel*: ``int`` Select a Transfer Request signal. See section 2.5.3 in the RP2040
|
||||
datasheet for details.
|
||||
|
||||
- *irq_quiet*: ``bool`` Do not generate interrupt at the end of each transfer. Interrupts
|
||||
will instead be generated when a zero value is written to the trigger
|
||||
register, which will halt a sequence of chained transfers (default:
|
||||
``True``).
|
||||
|
||||
- *bswap*: ``bool`` If set to true, bytes in words or half-words will be reversed before
|
||||
writing (default: ``True``).
|
||||
|
||||
- *sniff_en*: ``bool`` Set to ``True`` to allow data to be accessed by the chips sniff
|
||||
hardware (default: ``False``).
|
||||
|
||||
- *write_err*: ``bool`` Setting this to ``True`` will clear a previously reported write
|
||||
error.
|
||||
|
||||
- *read_err*: ``bool`` Setting this to ``True`` will clear a previously reported read
|
||||
error.
|
||||
|
||||
See the description of the ``CH0_CTRL_TRIG`` register in section 2.5.7 of the RP2040
|
||||
datasheet for details of all of these fields.
|
||||
|
||||
.. method:: DMA.unpack_ctrl(value)
|
||||
|
||||
Unpack a value for a DMA channel control register into a dictionary with key/value pairs
|
||||
for each of the fields in the control register. *value* is the ``ctrl`` register value
|
||||
to unpack.
|
||||
|
||||
This method will return values for all the keys that can be passed to ``DMA.pack_ctrl``.
|
||||
In addition, it will also return the read-only flags in the control register: ``busy``,
|
||||
which goes high when a transfer starts and low when it ends, and ``ahb_err``, which is
|
||||
the logical OR of the ``read_err`` and ``write_err`` flags. These values will be ignored
|
||||
when packing, so that the dictionary created by unpacking a control register can be used
|
||||
directly as the keyword arguments for packing.
|
||||
|
||||
.. method:: DMA.active([value])
|
||||
|
||||
Gets or sets whether the DMA channel is currently running.
|
||||
|
||||
>>> sm.active()
|
||||
0
|
||||
>>> sm.active(1)
|
||||
>>> while sm.active():
|
||||
... pass
|
||||
|
||||
Attributes
|
||||
----------
|
||||
|
||||
.. attribute:: DMA.read
|
||||
|
||||
This attribute reflects the address from which the next bus transfer
|
||||
will read. It may be written with either an integer or an object
|
||||
that supports the buffer protocol and doing so has immediate effect.
|
||||
|
||||
.. attribute:: DMA.write
|
||||
|
||||
This attribute reflects the address to which the next bus transfer
|
||||
will write. It may be written with either an integer or an object
|
||||
that supports the buffer protocol and doing so has immediate effect.
|
||||
|
||||
.. attribute:: DMA.count
|
||||
|
||||
Reading this attribute will return the number of remaining bus
|
||||
transfers in the *current* transfer sequence. Writing this attribute
|
||||
sets the total number of transfers to be the *next* transfer sequence.
|
||||
|
||||
.. attribute:: DMA.ctrl
|
||||
|
||||
This attribute reflects DMA channel control register. It is typically written
|
||||
with an integer packed using the :meth:`DMA.pack_ctrl()` method. The returned
|
||||
register value can be unpacked using the :meth:`DMA.unpack_ctrl()` method.
|
||||
|
||||
.. attribute:: DMA.channel
|
||||
|
||||
The channel number of the DMA channel. This can be passed in the ``chain_to``
|
||||
argument of `DMA.pack_ctrl()` on another channel to allow DMA chaining.
|
||||
|
||||
.. attribute:: DMA.registers
|
||||
|
||||
This attribute is an array-like object that allows direct access to
|
||||
the DMA channel's registers. The index is by word, rather than by byte,
|
||||
so the register indices are the register address offsets divided by 4.
|
||||
See the RP2040 data sheet for register details.
|
||||
|
||||
Chaining and trigger register access
|
||||
------------------------------------
|
||||
|
||||
The DMA controller in the RP2040 offers a couple advanced features to allow one DMA channel
|
||||
to initiate a transfer on another channel. One is the use of the ``chain_to`` value in the
|
||||
control register and the other is writing to one of the DMA channel's registers that has a
|
||||
trigger effect. When coupled with the ability to have one DMA channel write directly to the
|
||||
`DMA.registers` of another channel, this allows for complex transactions to be performed
|
||||
without any CPU intervention.
|
||||
|
||||
Below is an example of using both chaining and register
|
||||
triggering to implement gathering of multiple blocks of data into a single destination. Full
|
||||
details of these features can be found in section 2.5 of the RP2040 data sheet and the code
|
||||
below is a Pythonic version of the example in sub-section 2.5.6.2.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from rp2 import DMA
|
||||
from uctypes import addressof
|
||||
from array import array
|
||||
|
||||
def gather_strings(string_list, buf):
|
||||
# We use two DMA channels. The first sends lengths and source addresses from the gather
|
||||
# list to the registers of the second. The second copies the data itself.
|
||||
gather_dma = DMA()
|
||||
buffer_dma = DMA()
|
||||
|
||||
# Pack up length/address pairs to be sent to the registers.
|
||||
gather_list = array("I")
|
||||
|
||||
for s in string_list:
|
||||
gather_list.append(len(s))
|
||||
gather_list.append(addressof(s))
|
||||
|
||||
gather_list.append(0)
|
||||
gather_list.append(0)
|
||||
|
||||
# When writing to the registers of the second DMA channel, we need to wrap the
|
||||
# write address on an 8-byte (1<<3 bytes) boundary. We write to the ``TRANS_COUNT``
|
||||
# and ``READ_ADD_TRIG`` registers in the last register alias (registers 14 and 15).
|
||||
gather_ctrl = gather_dma.pack_ctrl(ring_size=3, ring_sel=True)
|
||||
gather_dma.config(
|
||||
read=gather_list, write=buffer_dma.registers[14:16],
|
||||
count=2, ctrl=gather_ctrl
|
||||
)
|
||||
|
||||
# When copying the data, the transfer size is single bytes, and when completed we need
|
||||
# to chain back to the start another gather DMA transaction.
|
||||
buffer_ctrl = buffer_dma.pack_ctrl(size=0, chain_to=gather_dma.channel)
|
||||
# The read and count values will be set by the other DMA channel.
|
||||
buffer_dma.config(write=buf, ctrl=buffer_ctrl)
|
||||
|
||||
# Set the transfer in motion.
|
||||
gather_dma.active(1)
|
||||
|
||||
# Wait until all the register values have been sent
|
||||
end_address = addressof(gather_list) + 4 * len(gather_list)
|
||||
while gather_dma.read != end_address:
|
||||
pass
|
||||
|
||||
input = ["This is ", "a ", "test", " of the scatter", " gather", " process"]
|
||||
output = bytearray(64)
|
||||
|
||||
print(output)
|
||||
gather_strings(input, output)
|
||||
print(output)
|
||||
|
||||
This example idles while waiting for the transfer to complete; alternatively it could
|
||||
set an interrupt handler and return immediately.
|
@@ -32,5 +32,5 @@ Methods
|
||||
|
||||
These methods implement the simple and extended
|
||||
:ref:`block protocol <block-device-interface>` defined by
|
||||
:class:`vfs.AbstractBlockDev`.
|
||||
:class:`os.AbstractBlockDev`.
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user