Compare commits
No commits in common. "master" and "v1.17" have entirely different histories.
@ -1,36 +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
|
|
||||||
|
|
||||||
# all: Fix various spelling mistakes found by codespell 2.2.6.
|
|
||||||
cf490a70917a1b2d38ba9b58e763e0837d0f7ca7
|
|
||||||
|
|
||||||
# all: Fix spelling mistakes based on codespell check.
|
|
||||||
b1229efbd1509654dec6053865ab828d769e29db
|
|
||||||
|
|
||||||
# top: Update Python formatting to black "2023 stable style".
|
|
||||||
8b2748269244304854b3462cb8902952b4dcb892
|
|
||||||
|
|
||||||
# all: Reformat remaining C code that doesn't have a space after a comma.
|
|
||||||
5b700b0af90591d6b1a2c087bb8de6b7f1bfdd2d
|
|
||||||
|
|
||||||
# ports: Reformat more C and Python source code.
|
|
||||||
5c32111fa0e31e451b0f1666bdf926be2fdfd82c
|
|
||||||
|
|
||||||
# all: Update Python formatting to latest Black version 22.1.0.
|
|
||||||
ab2923dfa1174dc177f0a90cb00a7e4ff87958d2
|
|
||||||
|
|
||||||
# all: Update Python formatting to latest Black version 21.12b0.
|
|
||||||
3770fab33449a5dadf8eb06edfae0767e75320a6
|
|
||||||
|
|
||||||
# tools/gen-cpydiff.py: Fix formatting of doc strings for new Black.
|
# tools/gen-cpydiff.py: Fix formatting of doc strings for new Black.
|
||||||
0f78c36c5aa458a954eed39a46942209107a553e
|
0f78c36c5aa458a954eed39a46942209107a553e
|
||||||
|
|
||||||
|
|||||||
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -8,12 +8,10 @@
|
|||||||
|
|
||||||
# These are binary so should never be modified by git.
|
# These are binary so should never be modified by git.
|
||||||
*.a binary
|
*.a binary
|
||||||
*.ico binary
|
|
||||||
*.png binary
|
*.png binary
|
||||||
*.jpg binary
|
*.jpg binary
|
||||||
*.dxf binary
|
*.dxf binary
|
||||||
*.mpy binary
|
*.mpy binary
|
||||||
*.der binary
|
|
||||||
|
|
||||||
# These should also not be modified by git.
|
# These should also not be modified by git.
|
||||||
tests/basics/string_cr_conversion.py -text
|
tests/basics/string_cr_conversion.py -text
|
||||||
|
|||||||
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.
|
|
||||||
11
.github/ISSUE_TEMPLATE/config.yml
vendored
11
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,11 +0,0 @@
|
|||||||
blank_issues_enabled: false
|
|
||||||
contact_links:
|
|
||||||
- name: MicroPython GitHub Discussions
|
|
||||||
url: https://github.com/orgs/micropython/discussions
|
|
||||||
about: Community discussion about all things MicroPython. This is the best place to start if you have questions about using MicroPython or getting started with MicroPython development.
|
|
||||||
- name: MicroPython Documentation
|
|
||||||
url: https://docs.micropython.org/
|
|
||||||
about: Documentation for using and working with MicroPython and libraries.
|
|
||||||
- name: MicroPython Downloads
|
|
||||||
url: https://micropython.org/download/
|
|
||||||
about: Pre-built firmware and information for most supported boards.
|
|
||||||
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.
|
|
||||||
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.
|
|
||||||
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
|
|
||||||
12
.github/auto-comment.yml
vendored
12
.github/auto-comment.yml
vendored
@ -1,12 +0,0 @@
|
|||||||
# Comment to a new issue.
|
|
||||||
pullRequestOpened: |
|
|
||||||
Thank you for raising your pull request.
|
|
||||||
|
|
||||||
To ensure that all licensing criteria is met all repositories of the LVGL project apply a process called DCO (Developer's Certificate of Origin).
|
|
||||||
|
|
||||||
The text of DCO can be read here: https://developercertificate.org/
|
|
||||||
For a more detailed description see the [Documentation](https://docs.lvgl.io/latest/en/html/contributing/index.html#developer-certification-of-origin-dco) site.
|
|
||||||
|
|
||||||
By contributing to any repositories of the LVGL project you state that your contribution corresponds with the DCO.
|
|
||||||
|
|
||||||
No further action is required if your contribution fulfills the DCO. If you are not sure about it feel free to ask us in a comment.
|
|
||||||
7
.github/dependabot.yml
vendored
7
.github/dependabot.yml
vendored
@ -1,7 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
# Maintain dependencies for GitHub Actions
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
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) -->
|
|
||||||
|
|
||||||
17
.github/stale.yml
vendored
17
.github/stale.yml
vendored
@ -1,17 +0,0 @@
|
|||||||
# Number of days of inactivity before an issue becomes stale
|
|
||||||
daysUntilStale: 21
|
|
||||||
# Number of days of inactivity before a stale issue is closed
|
|
||||||
daysUntilClose: 7
|
|
||||||
# Issues with these labels will never be considered stale
|
|
||||||
exemptLabels:
|
|
||||||
- architecture
|
|
||||||
- pinned
|
|
||||||
# Label to use when marking an issue as stale
|
|
||||||
staleLabel: stale
|
|
||||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
|
||||||
markComment: >
|
|
||||||
This issue or pull request has been automatically marked as stale because it has not had
|
|
||||||
recent activity. It will be closed if no further activity occurs. Thank you
|
|
||||||
for your contributions.
|
|
||||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
|
||||||
closeComment: false
|
|
||||||
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
|
|
||||||
16
.github/workflows/code_formatting.yml
vendored
16
.github/workflows/code_formatting.yml
vendored
@ -2,19 +2,15 @@ name: Check code formatting
|
|||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
code-formatting:
|
build:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-python@v5
|
- uses: actions/setup-python@v1
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_c_code_formatting_setup
|
run: source tools/ci.sh && ci_code_formatting_setup
|
||||||
- name: Run code formatting
|
- name: Run code formatting
|
||||||
run: source tools/ci.sh && ci_c_code_formatting_run
|
run: source tools/ci.sh && ci_code_formatting_run
|
||||||
- name: Check code formatting
|
- name: Check code formatting
|
||||||
run: git diff --exit-code
|
run: git diff --exit-code
|
||||||
|
|||||||
30
.github/workflows/code_size.yml
vendored
30
.github/workflows/code_size.yml
vendored
@ -8,25 +8,15 @@ on:
|
|||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'py/**'
|
- 'py/**'
|
||||||
- 'extmod/**'
|
- 'extmod/**'
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
- 'lib/**'
|
||||||
- 'ports/bare-arm/**'
|
- 'ports/bare-arm/**'
|
||||||
- 'ports/mimxrt/**'
|
|
||||||
- 'ports/minimal/**'
|
- 'ports/minimal/**'
|
||||||
- 'ports/rp2/**'
|
|
||||||
- 'ports/samd/**'
|
|
||||||
- 'ports/stm32/**'
|
|
||||||
- 'ports/unix/**'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 100
|
fetch-depth: 100
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
@ -34,18 +24,4 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: source tools/ci.sh && ci_code_size_build
|
run: source tools/ci.sh && ci_code_size_build
|
||||||
- name: Compute code size difference
|
- name: Compute code size difference
|
||||||
run: tools/metrics.py diff ~/size0 ~/size1 | tee diff
|
run: tools/metrics.py diff --error-threshold 0 ~/size0 ~/size1
|
||||||
- name: Save PR number
|
|
||||||
if: github.event_name == 'pull_request'
|
|
||||||
env:
|
|
||||||
PR_NUMBER: ${{ github.event.number }}
|
|
||||||
run: echo $PR_NUMBER > pr_number
|
|
||||||
- name: Upload diff
|
|
||||||
if: github.event_name == 'pull_request'
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: code-size-report
|
|
||||||
path: |
|
|
||||||
diff
|
|
||||||
pr_number
|
|
||||||
retention-days: 1
|
|
||||||
|
|||||||
105
.github/workflows/code_size_comment.yml
vendored
105
.github/workflows/code_size_comment.yml
vendored
@ -1,105 +0,0 @@
|
|||||||
name: Code size comment
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_run:
|
|
||||||
workflows: [Check code size]
|
|
||||||
types: [completed]
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
comment:
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- name: 'Download artifact'
|
|
||||||
id: download-artifact
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
result-encoding: string
|
|
||||||
script: |
|
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
run_id: context.payload.workflow_run.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
const matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
|
|
||||||
return artifact.name == "code-size-report"
|
|
||||||
});
|
|
||||||
|
|
||||||
if (matchArtifact.length === 0) {
|
|
||||||
console.log('no matching artifact found');
|
|
||||||
console.log('result: "skip"');
|
|
||||||
|
|
||||||
return 'skip';
|
|
||||||
}
|
|
||||||
|
|
||||||
const download = await github.rest.actions.downloadArtifact({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
artifact_id: matchArtifact[0].id,
|
|
||||||
archive_format: 'zip',
|
|
||||||
});
|
|
||||||
|
|
||||||
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/code-size-report.zip`, Buffer.from(download.data));
|
|
||||||
|
|
||||||
console.log('artifact downloaded to `code-size-report.zip`');
|
|
||||||
console.log('result: "ok"');
|
|
||||||
|
|
||||||
return 'ok';
|
|
||||||
- name: 'Unzip artifact'
|
|
||||||
if: steps.download-artifact.outputs.result == 'ok'
|
|
||||||
run: unzip code-size-report.zip
|
|
||||||
- name: Post comment to pull request
|
|
||||||
if: steps.download-artifact.outputs.result == 'ok'
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
|
||||||
script: |
|
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
const prNumber = Number(fs.readFileSync('pr_number'));
|
|
||||||
const codeSizeReport = `Code size report:
|
|
||||||
|
|
||||||
\`\`\`
|
|
||||||
${fs.readFileSync('diff')}
|
|
||||||
\`\`\`
|
|
||||||
`;
|
|
||||||
|
|
||||||
const comments = await github.paginate(
|
|
||||||
github.rest.issues.listComments,
|
|
||||||
{
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: prNumber,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
comments.reverse();
|
|
||||||
|
|
||||||
const previousComment = comments.find(comment =>
|
|
||||||
comment.user.login === 'github-actions[bot]'
|
|
||||||
)
|
|
||||||
|
|
||||||
// if github-actions[bot] already made a comment, update it,
|
|
||||||
// otherwise create a new comment.
|
|
||||||
|
|
||||||
if (previousComment) {
|
|
||||||
await github.rest.issues.updateComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
comment_id: previousComment.id,
|
|
||||||
body: codeSizeReport,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: prNumber,
|
|
||||||
body: codeSizeReport,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
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.2.6 tomli
|
|
||||||
- run: codespell
|
|
||||||
|
|
||||||
8
.github/workflows/commit_formatting.yml
vendored
8
.github/workflows/commit_formatting.yml
vendored
@ -2,17 +2,13 @@ name: Check commit message formatting
|
|||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: '100'
|
fetch-depth: '100'
|
||||||
- uses: actions/setup-python@v5
|
- uses: actions/setup-python@v1
|
||||||
- name: Check commit message formatting
|
- name: Check commit message formatting
|
||||||
run: source tools/ci.sh && ci_commit_formatting_run
|
run: source tools/ci.sh && ci_commit_formatting_run
|
||||||
|
|||||||
11
.github/workflows/docs.yml
vendored
11
.github/workflows/docs.yml
vendored
@ -1,23 +1,18 @@
|
|||||||
name: Build docs
|
name: Build docs
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- docs/**
|
- docs/**
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-python@v5
|
- uses: actions/setup-python@v1
|
||||||
- name: Install Python packages
|
- name: Install Python packages
|
||||||
run: pip install -r docs/requirements.txt
|
run: pip install Sphinx
|
||||||
- name: Build docs
|
- name: Build docs
|
||||||
run: make -C docs/ html
|
run: make -C docs/ html
|
||||||
|
|||||||
25
.github/workflows/examples.yml
vendored
25
.github/workflows/examples.yml
vendored
@ -1,25 +0,0 @@
|
|||||||
name: Check examples
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- '.github/workflows/*.yml'
|
|
||||||
- 'examples/**'
|
|
||||||
- 'ports/unix/**'
|
|
||||||
- 'py/**'
|
|
||||||
- 'shared/**'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
embedding:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Build
|
|
||||||
run: make -C examples/embedding -f micropython_embed.mk && make -C examples/embedding
|
|
||||||
- name: Run
|
|
||||||
run: ./examples/embedding/embed | grep "hello world"
|
|
||||||
68
.github/workflows/js-port-v9.yml
vendored
68
.github/workflows/js-port-v9.yml
vendored
@ -1,68 +0,0 @@
|
|||||||
name: Build Javascript v9 port
|
|
||||||
env:
|
|
||||||
EM_VERSION: 2.0.31
|
|
||||||
EM_CACHE_FOLDER: 'emsdk-cache'
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ lvgl_javascript_v9 ]
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-deploy:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
ref: 'lvgl_javascript_v9'
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Setup cache
|
|
||||||
id: cache-system-libraries
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ${{env.EM_CACHE_FOLDER}}
|
|
||||||
key: ${{env.EM_VERSION}}-${{ runner.os }}
|
|
||||||
- uses: mymindstorm/setup-emsdk@v10
|
|
||||||
with:
|
|
||||||
version: ${{env.EM_VERSION}}
|
|
||||||
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
|
|
||||||
- name: Build SDL2
|
|
||||||
run: embuilder build sdl2
|
|
||||||
- name: Build FreeType
|
|
||||||
run: ./build_freetype.sh
|
|
||||||
working-directory: ports/javascript/scripts
|
|
||||||
- name: Build Rlottie
|
|
||||||
run: ./build_rlottie.sh
|
|
||||||
working-directory: ports/javascript/scripts
|
|
||||||
- name: Update submodules
|
|
||||||
run: make -j $(nproc) -C ports/javascript submodules
|
|
||||||
- name: Build mpy-cross
|
|
||||||
run: make -j $(nproc) -C mpy-cross
|
|
||||||
- name: Install node modules
|
|
||||||
run: npm install
|
|
||||||
working-directory: ports/javascript
|
|
||||||
- name: Build workers
|
|
||||||
run: npm run clean
|
|
||||||
working-directory: ports/javascript
|
|
||||||
- name: Build the javascript port
|
|
||||||
run: make -j $(nproc) -C ports/javascript
|
|
||||||
- name: Build frontend
|
|
||||||
run: npm run bundle
|
|
||||||
working-directory: ports/javascript
|
|
||||||
- name: Clean up unneeded files
|
|
||||||
run: rm -rf build .cache node_modules
|
|
||||||
working-directory: ports/javascript
|
|
||||||
- name: Retrieve version
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=VERSION_NAME::$(user_modules/lv_binding_micropython/lvgl/scripts/find_version.sh)"
|
|
||||||
id: version
|
|
||||||
- name: Deploy
|
|
||||||
uses: JamesIves/github-pages-deploy-action@4.1.3
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.LVGL_BOT_TOKEN }}
|
|
||||||
commit-message: ${{ env.GITHUB_SHA }}
|
|
||||||
branch: master
|
|
||||||
folder: ports/javascript/bundle_out
|
|
||||||
repository-name: lvgl/sim
|
|
||||||
target-folder: v${{ steps.version.outputs.VERSION_NAME }}/micropython/ports/javascript
|
|
||||||
33
.github/workflows/merge-to-js.yml
vendored
33
.github/workflows/merge-to-js.yml
vendored
@ -1,33 +0,0 @@
|
|||||||
name: Merge master branch to lvgl_javascript
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- 'master'
|
|
||||||
jobs:
|
|
||||||
merge-branch:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
steps:
|
|
||||||
- name: Wait for Unix port build to succeed
|
|
||||||
uses: fountainhead/action-wait-for-check@v1.0.0
|
|
||||||
id: wait-for-build
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
checkName: build
|
|
||||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
||||||
- name: Skip merge
|
|
||||||
run: exit 1
|
|
||||||
if: steps.wait-for-build.outputs.conclusion == 'failure'
|
|
||||||
- uses: actions/checkout@master
|
|
||||||
- name: Merge to lvgl_javascript branch
|
|
||||||
uses: devmasx/merge-branch@v1.1.0
|
|
||||||
with:
|
|
||||||
type: now
|
|
||||||
target_branch: 'lvgl_javascript_v9'
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
|
||||||
- name: Trigger Javascript port build
|
|
||||||
uses: benc-uk/workflow-dispatch@a69ac85ea87587e76bb4f262eb868205dfcab8e8
|
|
||||||
with:
|
|
||||||
workflow: Build Javascript v9 port
|
|
||||||
ref: ${{ github.event.ref }}
|
|
||||||
token: ${{ secrets.LVGL_BOT_TOKEN }}
|
|
||||||
29
.github/workflows/mpremote.yml
vendored
29
.github/workflows/mpremote.yml
vendored
@ -1,29 +0,0 @@
|
|||||||
name: Package mpremote
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- '.github/workflows/*.yml'
|
|
||||||
- 'tools/**'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
# Setting this to zero means fetch all history and tags,
|
|
||||||
# which hatch-vcs can use to discover the version tag.
|
|
||||||
fetch-depth: 0
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
- name: Install build tools
|
|
||||||
run: pip install build
|
|
||||||
- name: Build mpremote wheel
|
|
||||||
run: cd tools/mpremote && python -m build --wheel
|
|
||||||
- name: Archive mpremote wheel
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: mpremote
|
|
||||||
path: |
|
|
||||||
tools/mpremote/dist/mpremote*.whl
|
|
||||||
24
.github/workflows/mpy_format.yml
vendored
24
.github/workflows/mpy_format.yml
vendored
@ -1,24 +0,0 @@
|
|||||||
name: .mpy file format and tools
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- '.github/workflows/*.yml'
|
|
||||||
- 'examples/**'
|
|
||||||
- 'tests/**'
|
|
||||||
- 'tools/**'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-20.04 # use 20.04 to get python2
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install packages
|
|
||||||
run: source tools/ci.sh && ci_mpy_format_setup
|
|
||||||
- name: Test mpy-tool.py
|
|
||||||
run: source tools/ci.sh && ci_mpy_format_test
|
|
||||||
22
.github/workflows/ports.yml
vendored
22
.github/workflows/ports.yml
vendored
@ -1,22 +0,0 @@
|
|||||||
name: Build ports metadata
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- '.github/workflows/*.yml'
|
|
||||||
- 'tools/**'
|
|
||||||
- ports/**
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Build ports download metadata
|
|
||||||
run: mkdir boards && ./tools/autobuild/build-downloads.py . ./boards
|
|
||||||
7
.github/workflows/ports_cc3200.yml
vendored
7
.github/workflows/ports_cc3200.yml
vendored
@ -8,20 +8,15 @@ on:
|
|||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'py/**'
|
- 'py/**'
|
||||||
- 'extmod/**'
|
- 'extmod/**'
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
- 'lib/**'
|
||||||
- 'drivers/**'
|
- 'drivers/**'
|
||||||
- 'ports/cc3200/**'
|
- 'ports/cc3200/**'
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_cc3200_setup
|
run: source tools/ci.sh && ci_cc3200_setup
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|||||||
53
.github/workflows/ports_esp32.yml
vendored
53
.github/workflows/ports_esp32.yml
vendored
@ -8,50 +8,25 @@ on:
|
|||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'py/**'
|
- 'py/**'
|
||||||
- 'extmod/**'
|
- 'extmod/**'
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
- 'lib/**'
|
||||||
- 'drivers/**'
|
- 'drivers/**'
|
||||||
- 'ports/esp32/**'
|
- 'ports/esp32/**'
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_idf:
|
build_idf402:
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
ci_func: # names are functions in ci.sh
|
|
||||||
- esp32_build_cmod_spiram_s2
|
|
||||||
- esp32_build_s3_c3
|
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install packages
|
||||||
|
run: source tools/ci.sh && ci_esp32_idf402_setup
|
||||||
|
- name: Build
|
||||||
|
run: source tools/ci.sh && ci_esp32_build
|
||||||
|
|
||||||
- id: idf_ver
|
build_idf43:
|
||||||
name: Read the ESP-IDF version
|
runs-on: ubuntu-20.04
|
||||||
run: source tools/ci.sh && echo "IDF_VER=$IDF_VER" | tee "$GITHUB_OUTPUT"
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
- name: Cached ESP-IDF install
|
- name: Install packages
|
||||||
id: cache_esp_idf
|
run: source tools/ci.sh && ci_esp32_idf43_setup
|
||||||
uses: actions/cache@v4
|
- name: Build
|
||||||
with:
|
run: source tools/ci.sh && ci_esp32_build
|
||||||
path: |
|
|
||||||
./esp-idf/
|
|
||||||
~/.espressif/
|
|
||||||
!~/.espressif/dist/
|
|
||||||
~/.cache/pip/
|
|
||||||
key: esp-idf-${{ steps.idf_ver.outputs.IDF_VER }}
|
|
||||||
|
|
||||||
- name: Install ESP-IDF packages
|
|
||||||
if: steps.cache_esp_idf.outputs.cache-hit != 'true'
|
|
||||||
run: source tools/ci.sh && ci_esp32_idf_setup
|
|
||||||
|
|
||||||
- name: ccache
|
|
||||||
uses: hendrikmuhs/ccache-action@v1.2
|
|
||||||
with:
|
|
||||||
key: esp32-${{ matrix.ci_func }}
|
|
||||||
|
|
||||||
- name: Build ci_${{matrix.ci_func }}
|
|
||||||
run: source tools/ci.sh && ci_${{ matrix.ci_func }}
|
|
||||||
|
|||||||
7
.github/workflows/ports_esp8266.yml
vendored
7
.github/workflows/ports_esp8266.yml
vendored
@ -8,20 +8,15 @@ on:
|
|||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'py/**'
|
- 'py/**'
|
||||||
- 'extmod/**'
|
- 'extmod/**'
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
- 'lib/**'
|
||||||
- 'drivers/**'
|
- 'drivers/**'
|
||||||
- 'ports/esp8266/**'
|
- 'ports/esp8266/**'
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_esp8266_setup && ci_esp8266_path >> $GITHUB_PATH
|
run: source tools/ci.sh && ci_esp8266_setup && ci_esp8266_path >> $GITHUB_PATH
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|||||||
24
.github/workflows/ports_javascript.yml
vendored
Normal file
24
.github/workflows/ports_javascript.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
name: javascript port
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/*.yml'
|
||||||
|
- 'tools/**'
|
||||||
|
- 'py/**'
|
||||||
|
- 'extmod/**'
|
||||||
|
- 'lib/**'
|
||||||
|
- 'ports/javascript/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install packages
|
||||||
|
run: source tools/ci.sh && ci_javascript_setup
|
||||||
|
- name: Build
|
||||||
|
run: source tools/ci.sh && ci_javascript_build
|
||||||
|
- name: Run tests
|
||||||
|
run: source tools/ci.sh && ci_javascript_run_tests
|
||||||
12
.github/workflows/ports_mimxrt.yml
vendored
12
.github/workflows/ports_mimxrt.yml
vendored
@ -8,25 +8,15 @@ on:
|
|||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'py/**'
|
- 'py/**'
|
||||||
- 'extmod/**'
|
- 'extmod/**'
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
- 'lib/**'
|
||||||
- 'drivers/**'
|
- 'drivers/**'
|
||||||
- 'ports/mimxrt/**'
|
- 'ports/mimxrt/**'
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: 'micropython repo' # test build with space in path
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
with:
|
|
||||||
path: 'micropython repo'
|
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_mimxrt_setup
|
run: source tools/ci.sh && ci_mimxrt_setup
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|||||||
7
.github/workflows/ports_nrf.yml
vendored
7
.github/workflows/ports_nrf.yml
vendored
@ -8,20 +8,15 @@ on:
|
|||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'py/**'
|
- 'py/**'
|
||||||
- 'extmod/**'
|
- 'extmod/**'
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
- 'lib/**'
|
||||||
- 'drivers/**'
|
- 'drivers/**'
|
||||||
- 'ports/nrf/**'
|
- 'ports/nrf/**'
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_nrf_setup
|
run: source tools/ci.sh && ci_nrf_setup
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|||||||
7
.github/workflows/ports_powerpc.yml
vendored
7
.github/workflows/ports_powerpc.yml
vendored
@ -8,20 +8,15 @@ on:
|
|||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'py/**'
|
- 'py/**'
|
||||||
- 'extmod/**'
|
- 'extmod/**'
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
- 'lib/**'
|
||||||
- 'drivers/**'
|
- 'drivers/**'
|
||||||
- 'ports/powerpc/**'
|
- 'ports/powerpc/**'
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_powerpc_setup
|
run: source tools/ci.sh && ci_powerpc_setup
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|||||||
27
.github/workflows/ports_qemu-arm.yml
vendored
Normal file
27
.github/workflows/ports_qemu-arm.yml
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
name: qemu-arm port
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/*.yml'
|
||||||
|
- 'tools/**'
|
||||||
|
- 'py/**'
|
||||||
|
- 'extmod/**'
|
||||||
|
- 'lib/**'
|
||||||
|
- 'drivers/**'
|
||||||
|
- 'ports/qemu-arm/**'
|
||||||
|
- 'tests/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_and_test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install packages
|
||||||
|
run: source tools/ci.sh && ci_qemu_arm_setup
|
||||||
|
- name: Build and run test suite
|
||||||
|
run: source tools/ci.sh && ci_qemu_arm_build
|
||||||
|
- name: Print failures
|
||||||
|
if: failure()
|
||||||
|
run: grep --text "FAIL" ports/qemu-arm/build/console.out
|
||||||
44
.github/workflows/ports_qemu.yml
vendored
44
.github/workflows/ports_qemu.yml
vendored
@ -1,44 +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:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install packages
|
|
||||||
run: source tools/ci.sh && ci_qemu_setup_arm
|
|
||||||
- name: Build and run test suite
|
|
||||||
run: source tools/ci.sh && ci_qemu_build_arm
|
|
||||||
- name: Print failures
|
|
||||||
if: failure()
|
|
||||||
run: tests/run-tests.py --print-failures
|
|
||||||
|
|
||||||
build_and_test_rv32:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install packages
|
|
||||||
run: source tools/ci.sh && ci_qemu_setup_rv32
|
|
||||||
- name: Build and run test suite
|
|
||||||
run: source tools/ci.sh && ci_qemu_build_rv32
|
|
||||||
- name: Print failures
|
|
||||||
if: failure()
|
|
||||||
run: tests/run-tests.py --print-failures
|
|
||||||
29
.github/workflows/ports_renesas-ra.yml
vendored
29
.github/workflows/ports_renesas-ra.yml
vendored
@ -1,29 +0,0 @@
|
|||||||
name: renesas-ra port
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- '.github/workflows/*.yml'
|
|
||||||
- 'tools/**'
|
|
||||||
- 'py/**'
|
|
||||||
- 'extmod/**'
|
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
|
||||||
- 'drivers/**'
|
|
||||||
- 'ports/renesas-ra/**'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build_renesas_ra_board:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install packages
|
|
||||||
run: source tools/ci.sh && ci_renesas_ra_setup
|
|
||||||
- name: Build
|
|
||||||
run: source tools/ci.sh && ci_renesas_ra_board_build
|
|
||||||
|
|
||||||
12
.github/workflows/ports_rp2.yml
vendored
12
.github/workflows/ports_rp2.yml
vendored
@ -8,25 +8,15 @@ on:
|
|||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'py/**'
|
- 'py/**'
|
||||||
- 'extmod/**'
|
- 'extmod/**'
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
- 'lib/**'
|
||||||
- 'drivers/**'
|
- 'drivers/**'
|
||||||
- 'ports/rp2/**'
|
- 'ports/rp2/**'
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: 'micropython repo' # test build with space in path
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
with:
|
|
||||||
path: 'micropython repo'
|
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_rp2_setup
|
run: source tools/ci.sh && ci_rp2_setup
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|||||||
7
.github/workflows/ports_samd.yml
vendored
7
.github/workflows/ports_samd.yml
vendored
@ -8,20 +8,15 @@ on:
|
|||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'py/**'
|
- 'py/**'
|
||||||
- 'extmod/**'
|
- 'extmod/**'
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
- 'lib/**'
|
||||||
- 'drivers/**'
|
- 'drivers/**'
|
||||||
- 'ports/samd/**'
|
- 'ports/samd/**'
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_samd_setup
|
run: source tools/ci.sh && ci_samd_setup
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|||||||
28
.github/workflows/ports_stm32.yml
vendored
28
.github/workflows/ports_stm32.yml
vendored
@ -8,29 +8,25 @@ on:
|
|||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'py/**'
|
- 'py/**'
|
||||||
- 'extmod/**'
|
- 'extmod/**'
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
- 'lib/**'
|
||||||
- 'drivers/**'
|
- 'drivers/**'
|
||||||
- 'ports/stm32/**'
|
- 'ports/stm32/**'
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_stm32:
|
build_pyb:
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
ci_func: # names are functions in ci.sh
|
|
||||||
- stm32_pyb_build
|
|
||||||
- stm32_nucleo_build
|
|
||||||
- stm32_misc_build
|
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_stm32_setup
|
run: source tools/ci.sh && ci_stm32_setup
|
||||||
- name: Build ci_${{matrix.ci_func }}
|
- name: Build
|
||||||
run: source tools/ci.sh && ci_${{ matrix.ci_func }}
|
run: source tools/ci.sh && ci_stm32_pyb_build
|
||||||
|
|
||||||
|
build_nucleo:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install packages
|
||||||
|
run: source tools/ci.sh && ci_stm32_setup
|
||||||
|
- name: Build
|
||||||
|
run: source tools/ci.sh && ci_stm32_nucleo_build
|
||||||
|
|||||||
23
.github/workflows/ports_teensy.yml
vendored
Normal file
23
.github/workflows/ports_teensy.yml
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
name: teensy port
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/*.yml'
|
||||||
|
- 'tools/**'
|
||||||
|
- 'py/**'
|
||||||
|
- 'extmod/**'
|
||||||
|
- 'lib/**'
|
||||||
|
- 'drivers/**'
|
||||||
|
- 'ports/teensy/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install packages
|
||||||
|
run: source tools/ci.sh && ci_teensy_setup
|
||||||
|
- name: Build
|
||||||
|
run: source tools/ci.sh && ci_teensy_build
|
||||||
75
.github/workflows/ports_unix.yml
vendored
75
.github/workflows/ports_unix.yml
vendored
@ -8,22 +8,16 @@ on:
|
|||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'py/**'
|
- 'py/**'
|
||||||
- 'extmod/**'
|
- 'extmod/**'
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
- 'lib/**'
|
||||||
- 'examples/**'
|
- 'examples/**'
|
||||||
- 'mpy-cross/**'
|
|
||||||
- 'ports/unix/**'
|
- 'ports/unix/**'
|
||||||
- 'tests/**'
|
- 'tests/**'
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
minimal:
|
minimal:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Build
|
- name: Build
|
||||||
run: source tools/ci.sh && ci_unix_minimal_build
|
run: source tools/ci.sh && ci_unix_minimal_build
|
||||||
- name: Run main test suite
|
- name: Run main test suite
|
||||||
@ -35,34 +29,36 @@ jobs:
|
|||||||
reproducible:
|
reproducible:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Build with reproducible date
|
- name: Build with reproducible date
|
||||||
run: source tools/ci.sh && ci_unix_minimal_build
|
run: source tools/ci.sh && ci_unix_minimal_build
|
||||||
env:
|
env:
|
||||||
SOURCE_DATE_EPOCH: 1234567890
|
SOURCE_DATE_EPOCH: 1234567890
|
||||||
- name: Check reproducible build date
|
- name: Check reproducible build date
|
||||||
run: echo | ports/unix/build-minimal/micropython -i | grep 'on 2009-02-13;'
|
run: echo | ports/unix/micropython-minimal -i | grep 'on 2009-02-13;'
|
||||||
|
|
||||||
standard:
|
standard:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Build
|
- name: Build
|
||||||
run: source tools/ci.sh && ci_unix_standard_build
|
run: source tools/ci.sh && ci_unix_standard_build
|
||||||
- name: Run main test suite
|
- name: Run main test suite
|
||||||
run: source tools/ci.sh && ci_unix_standard_run_tests
|
run: source tools/ci.sh && ci_unix_standard_run_tests
|
||||||
|
- name: Run performance benchmarks
|
||||||
|
run: source tools/ci.sh && ci_unix_standard_run_perfbench
|
||||||
- name: Print failures
|
- name: Print failures
|
||||||
if: failure()
|
if: failure()
|
||||||
run: tests/run-tests.py --print-failures
|
run: tests/run-tests.py --print-failures
|
||||||
|
|
||||||
standard_v2:
|
dev:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Build
|
- name: Build
|
||||||
run: source tools/ci.sh && ci_unix_standard_v2_build
|
run: source tools/ci.sh && ci_unix_dev_build
|
||||||
- name: Run main test suite
|
- name: Run main test suite
|
||||||
run: source tools/ci.sh && ci_unix_standard_v2_run_tests
|
run: source tools/ci.sh && ci_unix_dev_run_tests
|
||||||
- name: Print failures
|
- name: Print failures
|
||||||
if: failure()
|
if: failure()
|
||||||
run: tests/run-tests.py --print-failures
|
run: tests/run-tests.py --print-failures
|
||||||
@ -70,15 +66,13 @@ jobs:
|
|||||||
coverage:
|
coverage:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_unix_coverage_setup
|
run: source tools/ci.sh && ci_unix_coverage_setup
|
||||||
- name: Build
|
- name: Build
|
||||||
run: source tools/ci.sh && ci_unix_coverage_build
|
run: source tools/ci.sh && ci_unix_coverage_build
|
||||||
- name: Run main test suite
|
- name: Run main test suite
|
||||||
run: source tools/ci.sh && ci_unix_coverage_run_tests
|
run: source tools/ci.sh && ci_unix_coverage_run_tests
|
||||||
- name: Test merging .mpy files
|
|
||||||
run: source tools/ci.sh && ci_unix_coverage_run_mpy_merge_tests
|
|
||||||
- name: Build native mpy modules
|
- name: Build native mpy modules
|
||||||
run: source tools/ci.sh && ci_native_mpy_modules_build
|
run: source tools/ci.sh && ci_native_mpy_modules_build
|
||||||
- name: Test importing .mpy generated by mpy_ld.py
|
- name: Test importing .mpy generated by mpy_ld.py
|
||||||
@ -88,19 +82,18 @@ jobs:
|
|||||||
(cd ports/unix && gcov -o build-coverage/py ../../py/*.c || true)
|
(cd ports/unix && gcov -o build-coverage/py ../../py/*.c || true)
|
||||||
(cd ports/unix && gcov -o build-coverage/extmod ../../extmod/*.c || true)
|
(cd ports/unix && gcov -o build-coverage/extmod ../../extmod/*.c || true)
|
||||||
- name: Upload coverage to Codecov
|
- name: Upload coverage to Codecov
|
||||||
uses: codecov/codecov-action@v4
|
uses: codecov/codecov-action@v1
|
||||||
with:
|
with:
|
||||||
fail_ci_if_error: true
|
fail_ci_if_error: true
|
||||||
verbose: true
|
verbose: true
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
- name: Print failures
|
- name: Print failures
|
||||||
if: failure()
|
if: failure()
|
||||||
run: tests/run-tests.py --print-failures
|
run: tests/run-tests.py --print-failures
|
||||||
|
|
||||||
coverage_32bit:
|
coverage_32bit:
|
||||||
runs-on: ubuntu-20.04 # use 20.04 to get libffi-dev:i386
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_unix_32bit_setup
|
run: source tools/ci.sh && ci_unix_32bit_setup
|
||||||
- name: Build
|
- name: Build
|
||||||
@ -116,9 +109,9 @@ jobs:
|
|||||||
run: tests/run-tests.py --print-failures
|
run: tests/run-tests.py --print-failures
|
||||||
|
|
||||||
nanbox:
|
nanbox:
|
||||||
runs-on: ubuntu-20.04 # use 20.04 to get python2, and libffi-dev:i386
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_unix_32bit_setup
|
run: source tools/ci.sh && ci_unix_32bit_setup
|
||||||
- name: Build
|
- name: Build
|
||||||
@ -132,7 +125,7 @@ jobs:
|
|||||||
float:
|
float:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Build
|
- name: Build
|
||||||
run: source tools/ci.sh && ci_unix_float_build
|
run: source tools/ci.sh && ci_unix_float_build
|
||||||
- name: Run main test suite
|
- name: Run main test suite
|
||||||
@ -144,7 +137,7 @@ jobs:
|
|||||||
stackless_clang:
|
stackless_clang:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_unix_clang_setup
|
run: source tools/ci.sh && ci_unix_clang_setup
|
||||||
- name: Build
|
- name: Build
|
||||||
@ -158,7 +151,7 @@ jobs:
|
|||||||
float_clang:
|
float_clang:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_unix_clang_setup
|
run: source tools/ci.sh && ci_unix_clang_setup
|
||||||
- name: Build
|
- name: Build
|
||||||
@ -172,7 +165,7 @@ jobs:
|
|||||||
settrace:
|
settrace:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Build
|
- name: Build
|
||||||
run: source tools/ci.sh && ci_unix_settrace_build
|
run: source tools/ci.sh && ci_unix_settrace_build
|
||||||
- name: Run main test suite
|
- name: Run main test suite
|
||||||
@ -184,7 +177,7 @@ jobs:
|
|||||||
settrace_stackless:
|
settrace_stackless:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Build
|
- name: Build
|
||||||
run: source tools/ci.sh && ci_unix_settrace_stackless_build
|
run: source tools/ci.sh && ci_unix_settrace_stackless_build
|
||||||
- name: Run main test suite
|
- name: Run main test suite
|
||||||
@ -194,12 +187,10 @@ jobs:
|
|||||||
run: tests/run-tests.py --print-failures
|
run: tests/run-tests.py --print-failures
|
||||||
|
|
||||||
macos:
|
macos:
|
||||||
runs-on: macos-latest
|
runs-on: macos-11.0
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-python@v5
|
- uses: actions/setup-python@v1
|
||||||
with:
|
|
||||||
python-version: '3.8'
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: source tools/ci.sh && ci_unix_macos_build
|
run: source tools/ci.sh && ci_unix_macos_build
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
@ -211,7 +202,7 @@ jobs:
|
|||||||
qemu_mips:
|
qemu_mips:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_unix_qemu_mips_setup
|
run: source tools/ci.sh && ci_unix_qemu_mips_setup
|
||||||
- name: Build
|
- name: Build
|
||||||
@ -225,7 +216,7 @@ jobs:
|
|||||||
qemu_arm:
|
qemu_arm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_unix_qemu_arm_setup
|
run: source tools/ci.sh && ci_unix_qemu_arm_setup
|
||||||
- name: Build
|
- name: Build
|
||||||
@ -235,17 +226,3 @@ jobs:
|
|||||||
- name: Print failures
|
- name: Print failures
|
||||||
if: failure()
|
if: failure()
|
||||||
run: tests/run-tests.py --print-failures
|
run: tests/run-tests.py --print-failures
|
||||||
|
|
||||||
qemu_riscv64:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
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
|
|
||||||
|
|||||||
32
.github/workflows/ports_webassembly.yml
vendored
32
.github/workflows/ports_webassembly.yml
vendored
@ -1,32 +0,0 @@
|
|||||||
name: webassembly port
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- '.github/workflows/*.yml'
|
|
||||||
- 'tools/**'
|
|
||||||
- 'py/**'
|
|
||||||
- 'extmod/**'
|
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
|
||||||
- 'ports/webassembly/**'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install packages
|
|
||||||
run: source tools/ci.sh && ci_webassembly_setup
|
|
||||||
- name: Build
|
|
||||||
run: source tools/ci.sh && ci_webassembly_build
|
|
||||||
- name: Run tests
|
|
||||||
run: source tools/ci.sh && ci_webassembly_run_tests
|
|
||||||
- name: Print failures
|
|
||||||
if: failure()
|
|
||||||
run: tests/run-tests.py --print-failures
|
|
||||||
127
.github/workflows/ports_windows.yml
vendored
127
.github/workflows/ports_windows.yml
vendored
@ -8,138 +8,15 @@ on:
|
|||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'py/**'
|
- 'py/**'
|
||||||
- 'extmod/**'
|
- 'extmod/**'
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
- 'lib/**'
|
||||||
- 'ports/unix/**'
|
- 'ports/unix/**'
|
||||||
- 'ports/windows/**'
|
- 'ports/windows/**'
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-vs:
|
build:
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
platform: [x86, x64]
|
|
||||||
configuration: [Debug, Release]
|
|
||||||
variant: [dev, standard]
|
|
||||||
visualstudio: ['2017', '2019', '2022']
|
|
||||||
include:
|
|
||||||
- visualstudio: '2017'
|
|
||||||
runner: windows-latest
|
|
||||||
vs_version: '[15, 16)'
|
|
||||||
- visualstudio: '2019'
|
|
||||||
runner: windows-2019
|
|
||||||
vs_version: '[16, 17)'
|
|
||||||
- visualstudio: '2022'
|
|
||||||
runner: windows-2022
|
|
||||||
vs_version: '[17, 18)'
|
|
||||||
# trim down the number of jobs in the matrix
|
|
||||||
exclude:
|
|
||||||
- variant: standard
|
|
||||||
configuration: Debug
|
|
||||||
- visualstudio: '2019'
|
|
||||||
configuration: Debug
|
|
||||||
env:
|
|
||||||
CI_BUILD_CONFIGURATION: ${{ matrix.configuration }}
|
|
||||||
runs-on: ${{ matrix.runner }}
|
|
||||||
steps:
|
|
||||||
- name: Install Visual Studio 2017
|
|
||||||
if: matrix.visualstudio == '2017'
|
|
||||||
run: |
|
|
||||||
choco install visualstudio2017buildtools
|
|
||||||
choco install visualstudio2017-workload-vctools
|
|
||||||
choco install windows-sdk-8.1
|
|
||||||
- uses: microsoft/setup-msbuild@v2
|
|
||||||
with:
|
|
||||||
vs-version: ${{ matrix.vs_version }}
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
if: matrix.runner == 'windows-2019'
|
|
||||||
with:
|
|
||||||
python-version: '3.9'
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Build mpy-cross.exe
|
|
||||||
run: msbuild mpy-cross\mpy-cross.vcxproj -maxcpucount -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }}
|
|
||||||
- name: Update submodules
|
|
||||||
run: git submodule update --init lib/micropython-lib
|
|
||||||
- name: Build micropython.exe
|
|
||||||
run: msbuild ports\windows\micropython.vcxproj -maxcpucount -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }} -property:PyVariant=${{ matrix.variant }}
|
|
||||||
- name: Get micropython.exe path
|
|
||||||
id: get_path
|
|
||||||
run: |
|
|
||||||
$exePath="$(msbuild ports\windows\micropython.vcxproj -nologo -v:m -t:ShowTargetPath -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }} -property:PyVariant=${{ matrix.variant }})"
|
|
||||||
echo ("micropython=" + $exePath.Trim()) >> $env:GITHUB_OUTPUT
|
|
||||||
- name: Run tests
|
|
||||||
id: test
|
|
||||||
env:
|
|
||||||
MICROPY_MICROPYTHON: ${{ steps.get_path.outputs.micropython }}
|
|
||||||
working-directory: tests
|
|
||||||
run: python run-tests.py
|
|
||||||
- name: Print failures
|
|
||||||
if: failure() && steps.test.conclusion == 'failure'
|
|
||||||
working-directory: tests
|
|
||||||
run: python run-tests.py --print-failures
|
|
||||||
- name: Run mpy tests
|
|
||||||
id: test_mpy
|
|
||||||
env:
|
|
||||||
MICROPY_MICROPYTHON: ${{ steps.get_path.outputs.micropython }}
|
|
||||||
working-directory: tests
|
|
||||||
run: python run-tests.py --via-mpy -d basics float micropython
|
|
||||||
- name: Print mpy failures
|
|
||||||
if: failure() && steps.test_mpy.conclusion == 'failure'
|
|
||||||
working-directory: tests
|
|
||||||
run: python run-tests.py --print-failures
|
|
||||||
|
|
||||||
build-mingw:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
variant: [dev, standard]
|
|
||||||
sys: [mingw32, mingw64]
|
|
||||||
include:
|
|
||||||
- sys: mingw32
|
|
||||||
env: i686
|
|
||||||
- sys: mingw64
|
|
||||||
env: x86_64
|
|
||||||
runs-on: windows-2022
|
|
||||||
env:
|
|
||||||
CHERE_INVOKING: enabled_from_arguments
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: msys2 {0}
|
|
||||||
steps:
|
|
||||||
- uses: msys2/setup-msys2@v2
|
|
||||||
with:
|
|
||||||
msystem: ${{ matrix.sys }}
|
|
||||||
update: true
|
|
||||||
install: >-
|
|
||||||
make
|
|
||||||
mingw-w64-${{ matrix.env }}-gcc
|
|
||||||
pkg-config
|
|
||||||
mingw-w64-${{ matrix.env }}-python3
|
|
||||||
git
|
|
||||||
diffutils
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Build mpy-cross.exe
|
|
||||||
run: make -C mpy-cross -j2
|
|
||||||
- name: Update submodules
|
|
||||||
run: make -C ports/windows VARIANT=${{ matrix.variant }} submodules
|
|
||||||
- name: Build micropython.exe
|
|
||||||
run: make -C ports/windows -j2 VARIANT=${{ matrix.variant }}
|
|
||||||
- name: Run tests
|
|
||||||
id: test
|
|
||||||
run: make -C ports/windows test_full VARIANT=${{ matrix.variant }}
|
|
||||||
- name: Print failures
|
|
||||||
if: failure() && steps.test.conclusion == 'failure'
|
|
||||||
working-directory: tests
|
|
||||||
run: python run-tests.py --print-failures
|
|
||||||
|
|
||||||
cross-build-on-linux:
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_windows_setup
|
run: source tools/ci.sh && ci_windows_setup
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|||||||
21
.github/workflows/ports_zephyr.yml
vendored
21
.github/workflows/ports_zephyr.yml
vendored
@ -8,36 +8,17 @@ on:
|
|||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'py/**'
|
- 'py/**'
|
||||||
- 'extmod/**'
|
- 'extmod/**'
|
||||||
- 'shared/**'
|
|
||||||
- 'lib/**'
|
- 'lib/**'
|
||||||
- 'ports/zephyr/**'
|
- 'ports/zephyr/**'
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: jlumbroso/free-disk-space@main
|
- uses: actions/checkout@v2
|
||||||
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
|
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: source tools/ci.sh && ci_zephyr_setup
|
run: source tools/ci.sh && ci_zephyr_setup
|
||||||
- name: Install Zephyr
|
- name: Install Zephyr
|
||||||
run: source tools/ci.sh && ci_zephyr_install
|
run: source tools/ci.sh && ci_zephyr_install
|
||||||
- name: Build
|
- name: Build
|
||||||
run: source tools/ci.sh && ci_zephyr_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
|
|
||||||
|
|||||||
31
.github/workflows/rp2_port.yml
vendored
31
.github/workflows/rp2_port.yml
vendored
@ -1,31 +0,0 @@
|
|||||||
name: rp2 port
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
board: [PICO]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: arm-none-eabi-gcc
|
|
||||||
uses: carlosperate/arm-none-eabi-gcc-action@v1.3.0
|
|
||||||
with:
|
|
||||||
release: '9-2019-q4' # The arm-none-eabi-gcc release to use.
|
|
||||||
- name: Initialize lv_bindings submodule
|
|
||||||
run: git submodule update --init --recursive user_modules/lv_binding_micropython
|
|
||||||
- name: Initialize Micropython submodules
|
|
||||||
run: make -C ports/rp2 BOARD=${{ matrix.board }} USER_C_MODULES=../../user_modules/lv_binding_micropython/bindings.cmake submodules
|
|
||||||
- name: Build mpy-cross
|
|
||||||
run: make -j $(nproc) -C mpy-cross
|
|
||||||
- name: Build ${{ matrix.board }}
|
|
||||||
run: make -j $(nproc) -C ports/rp2 BOARD=${{ matrix.board }} USER_C_MODULES=../../user_modules/lv_binding_micropython/bindings.cmake
|
|
||||||
- uses: actions/upload-artifact@v2
|
|
||||||
if: ${{ env.GITHUB_EVENT_NAME }} == 'push'
|
|
||||||
with:
|
|
||||||
name: ${{ matrix.board }}.hex
|
|
||||||
path: ports/rp2/build-${{ matrix.board }}/firmware.elf
|
|
||||||
15
.github/workflows/ruff.yml
vendored
15
.github/workflows/ruff.yml
vendored
@ -1,15 +0,0 @@
|
|||||||
name: Python code lint and formatting with ruff
|
|
||||||
|
|
||||||
on: [push, pull_request]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ruff:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Initialize lv_bindings submodule
|
|
||||||
run: git submodule update --init --recursive user_modules/lv_binding_micropython
|
|
||||||
# ruff version should be kept in sync with .pre-commit-config.yaml
|
|
||||||
- run: pip install --user ruff==0.1.3
|
|
||||||
- run: ruff check --output-format=github .
|
|
||||||
- run: ruff format --diff .
|
|
||||||
29
.github/workflows/stm32_port.yml
vendored
29
.github/workflows/stm32_port.yml
vendored
@ -1,29 +0,0 @@
|
|||||||
name: stm32 port
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
board: [STM32F7DISC]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: arm-none-eabi-gcc
|
|
||||||
uses: carlosperate/arm-none-eabi-gcc-action@v1.3.0
|
|
||||||
with:
|
|
||||||
release: '9-2019-q4' # The arm-none-eabi-gcc release to use.
|
|
||||||
- name: Update submodules
|
|
||||||
run: git submodule update --init --recursive
|
|
||||||
- name: Build mpy-cross
|
|
||||||
run: make -j $(nproc) -C mpy-cross
|
|
||||||
- name: Build ${{ matrix.board }}
|
|
||||||
run: make -j $(nproc) -C ports/stm32 BOARD=${{ matrix.board }}
|
|
||||||
- uses: actions/upload-artifact@v2
|
|
||||||
if: ${{ env.GITHUB_EVENT_NAME }} == 'push'
|
|
||||||
with:
|
|
||||||
name: ${{ matrix.board }}.hex
|
|
||||||
path: ports/stm32/build-${{ matrix.board }}/firmware.hex
|
|
||||||
31
.github/workflows/unix_port.yml
vendored
31
.github/workflows/unix_port.yml
vendored
@ -1,31 +0,0 @@
|
|||||||
name: unix port
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Install Dependencies
|
|
||||||
run: |
|
|
||||||
sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse"
|
|
||||||
sudo apt-get update -y -qq
|
|
||||||
sudo apt-get install libsdl2-dev parallel libfreetype-dev librlottie-dev libavformat-dev libavcodec-dev libswscale-dev libavutil-dev
|
|
||||||
- name: Initialize lv_bindings submodule
|
|
||||||
run: git submodule update --init --recursive user_modules/lv_binding_micropython
|
|
||||||
- name: Update submodules
|
|
||||||
run: make -C ports/unix DEBUG=1 submodules
|
|
||||||
- name: Build mpy-cross
|
|
||||||
run: make -j $(nproc) -C mpy-cross
|
|
||||||
- name: Build the unix port
|
|
||||||
run: make -j $(nproc) -C ports/unix DEBUG=1
|
|
||||||
- name: Run tests
|
|
||||||
run: |
|
|
||||||
export XDG_RUNTIME_DIR=/tmp
|
|
||||||
user_modules/lv_binding_micropython/tests/run.sh
|
|
||||||
|
|
||||||
64
.gitignore
vendored
64
.gitignore
vendored
@ -1,30 +1,3 @@
|
|||||||
# This .gitignore file is intended to be minimal.
|
|
||||||
#
|
|
||||||
# If you find that you need additional rules, such as IDE temporary
|
|
||||||
# files, please do so either via a global .gitignore file (registered
|
|
||||||
# with core.excludesFile), or by adding private repository-specific
|
|
||||||
# rules to .git/info/exclude. See https://git-scm.com/docs/gitignore
|
|
||||||
# for more information.
|
|
||||||
|
|
||||||
# Build directories
|
|
||||||
build/
|
|
||||||
build-*/
|
|
||||||
docs/genrst/
|
|
||||||
|
|
||||||
# Test failure outputs and intermediate artefacts
|
|
||||||
tests/results/*
|
|
||||||
tests/ports/unix/ffi_lib.so
|
|
||||||
|
|
||||||
# Python cache files
|
|
||||||
__pycache__/
|
|
||||||
|
|
||||||
# Customized Makefile/project overrides
|
|
||||||
GNUmakefile
|
|
||||||
user.props
|
|
||||||
|
|
||||||
# MacOS desktop metadata files
|
|
||||||
.DS_Store
|
|
||||||
|
|
||||||
# Compiled Sources
|
# Compiled Sources
|
||||||
###################
|
###################
|
||||||
*.o
|
*.o
|
||||||
@ -36,9 +9,6 @@ user.props
|
|||||||
*.dis
|
*.dis
|
||||||
*.exe
|
*.exe
|
||||||
|
|
||||||
lextab.py
|
|
||||||
yacctab.py
|
|
||||||
|
|
||||||
# Packages
|
# Packages
|
||||||
############
|
############
|
||||||
|
|
||||||
@ -49,24 +19,30 @@ yacctab.py
|
|||||||
# VIM Swap Files
|
# VIM Swap Files
|
||||||
######################
|
######################
|
||||||
*.swp
|
*.swp
|
||||||
*.swo
|
|
||||||
*.swn
|
|
||||||
*.swi
|
|
||||||
*.swj
|
|
||||||
*.swk
|
|
||||||
*.swl
|
|
||||||
*.swm
|
|
||||||
|
|
||||||
# VIM Session Files
|
# Build directories
|
||||||
######################
|
######################
|
||||||
Session.vim
|
build/
|
||||||
|
build-*/
|
||||||
|
|
||||||
# CTags files
|
# Test failure outputs
|
||||||
######################
|
######################
|
||||||
tags
|
tests/results/*
|
||||||
TAGS
|
|
||||||
|
|
||||||
|
# Python cache files
|
||||||
######################
|
######################
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
ports/javascript/node_modules
|
# Customized Makefile/project overrides
|
||||||
.vscode/
|
######################
|
||||||
|
GNUmakefile
|
||||||
|
user.props
|
||||||
|
|
||||||
|
# Generated rst files
|
||||||
|
######################
|
||||||
|
genrst/
|
||||||
|
|
||||||
|
# MacOS desktop metadata files
|
||||||
|
######################
|
||||||
|
.DS_Store
|
||||||
|
|||||||
38
.gitmodules
vendored
38
.gitmodules
vendored
@ -3,17 +3,17 @@
|
|||||||
url = https://github.com/micropython/axtls.git
|
url = https://github.com/micropython/axtls.git
|
||||||
[submodule "lib/libffi"]
|
[submodule "lib/libffi"]
|
||||||
path = lib/libffi
|
path = lib/libffi
|
||||||
url = https://github.com/libffi/libffi
|
url = https://github.com/atgreen/libffi
|
||||||
[submodule "lib/lwip"]
|
[submodule "lib/lwip"]
|
||||||
path = lib/lwip
|
path = lib/lwip
|
||||||
url = https://github.com/lwip-tcpip/lwip.git
|
url = https://github.com/lwip-tcpip/lwip.git
|
||||||
[submodule "lib/berkeley-db-1.xx"]
|
[submodule "lib/berkeley-db-1.xx"]
|
||||||
path = 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"]
|
[submodule "lib/stm32lib"]
|
||||||
path = lib/stm32lib
|
path = lib/stm32lib
|
||||||
url = https://github.com/micropython/stm32lib
|
url = https://github.com/micropython/stm32lib
|
||||||
branch = work-F0-1.9.0+F4-1.16.0+F7-1.7.0+G0-1.5.1+G4-1.3.0+H7-1.6.0+L0-1.11.2+L1-1.10.3+L4-1.17.0+WB-1.10.0+WL-1.1.0
|
branch = work-F4-1.13.1+F7-1.5.0+L4-1.3.0
|
||||||
[submodule "lib/nrfx"]
|
[submodule "lib/nrfx"]
|
||||||
path = lib/nrfx
|
path = lib/nrfx
|
||||||
url = https://github.com/NordicSemiconductor/nrfx.git
|
url = https://github.com/NordicSemiconductor/nrfx.git
|
||||||
@ -23,13 +23,12 @@
|
|||||||
[submodule "lib/asf4"]
|
[submodule "lib/asf4"]
|
||||||
path = lib/asf4
|
path = lib/asf4
|
||||||
url = https://github.com/adafruit/asf4
|
url = https://github.com/adafruit/asf4
|
||||||
branch = circuitpython
|
|
||||||
[submodule "lib/tinyusb"]
|
[submodule "lib/tinyusb"]
|
||||||
path = lib/tinyusb
|
path = lib/tinyusb
|
||||||
url = https://github.com/hathach/tinyusb
|
url = https://github.com/hathach/tinyusb
|
||||||
[submodule "lib/mynewt-nimble"]
|
[submodule "lib/mynewt-nimble"]
|
||||||
path = lib/mynewt-nimble
|
path = lib/mynewt-nimble
|
||||||
url = https://github.com/micropython/mynewt-nimble.git
|
url = https://github.com/apache/mynewt-nimble.git
|
||||||
[submodule "lib/btstack"]
|
[submodule "lib/btstack"]
|
||||||
path = lib/btstack
|
path = lib/btstack
|
||||||
url = https://github.com/bluekitchen/btstack.git
|
url = https://github.com/bluekitchen/btstack.git
|
||||||
@ -42,32 +41,3 @@
|
|||||||
[submodule "lib/pico-sdk"]
|
[submodule "lib/pico-sdk"]
|
||||||
path = lib/pico-sdk
|
path = lib/pico-sdk
|
||||||
url = https://github.com/raspberrypi/pico-sdk.git
|
url = https://github.com/raspberrypi/pico-sdk.git
|
||||||
[submodule "lib/fsp"]
|
|
||||||
path = lib/fsp
|
|
||||||
url = https://github.com/renesas/fsp.git
|
|
||||||
[submodule "lib/wiznet"]
|
|
||||||
path = lib/wiznet5k
|
|
||||||
url = https://github.com/andrewleech/wiznet_ioLibrary_Driver.git
|
|
||||||
# Requires https://github.com/Wiznet/ioLibrary_Driver/pull/120
|
|
||||||
# url = https://github.com/Wiznet/ioLibrary_Driver.git
|
|
||||||
[submodule "lib/cyw43-driver"]
|
|
||||||
path = lib/cyw43-driver
|
|
||||||
url = https://github.com/georgerobotics/cyw43-driver.git
|
|
||||||
[submodule "lib/micropython-lib"]
|
|
||||||
path = lib/micropython-lib
|
|
||||||
url = https://github.com/micropython/micropython-lib.git
|
|
||||||
[submodule "lib/protobuf-c"]
|
|
||||||
path = lib/protobuf-c
|
|
||||||
url = https://github.com/protobuf-c/protobuf-c.git
|
|
||||||
[submodule "lib/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 "user_modules/lv_binding_micropython"]
|
|
||||||
path = user_modules/lv_binding_micropython
|
|
||||||
url = https://github.com/lvgl/lv_binding_micropython.git
|
|
||||||
|
|||||||
35
.gitpod
35
.gitpod
@ -1,35 +0,0 @@
|
|||||||
image:
|
|
||||||
file: .gitpod.Dockerfile
|
|
||||||
ports:
|
|
||||||
- port: 6080
|
|
||||||
protocol: "http"
|
|
||||||
onOpen: open-preview
|
|
||||||
- port: 5900
|
|
||||||
onOpen: ignore
|
|
||||||
tasks:
|
|
||||||
- init: |
|
|
||||||
make -C ports/unix DEBUG=1 submodules
|
|
||||||
make -j $(nproc) -C mpy-cross DEBUG=1
|
|
||||||
make -j $(nproc) -C ports/unix DEBUG=1
|
|
||||||
command: |
|
|
||||||
xrandr --fb 500x500 # Fix resolution for LVGL screens which are smaller
|
|
||||||
ports/unix/build-lvgl/micropython -i user_modules/lv_binding_micropython/examples/advanced_demo.py
|
|
||||||
vscode:
|
|
||||||
extensions:
|
|
||||||
- ms-vscode.cpptools
|
|
||||||
github:
|
|
||||||
prebuilds:
|
|
||||||
# enable for the master/default branch (defaults to true)
|
|
||||||
master: true
|
|
||||||
# enable for all branches in this repo (defaults to false)
|
|
||||||
branches: true
|
|
||||||
# enable for pull requests coming from this repo (defaults to true)
|
|
||||||
pullRequests: true
|
|
||||||
# enable for pull requests coming from forks (defaults to false)
|
|
||||||
pullRequestsFromForks: true
|
|
||||||
# add a "Review in Gitpod" button as a comment to pull requests (defaults to true)
|
|
||||||
addComment: true
|
|
||||||
# add a "Review in Gitpod" button to pull requests (defaults to false)
|
|
||||||
addBadge: false
|
|
||||||
# add a label once the prebuild is ready to pull requests (defaults to false)
|
|
||||||
addLabel: prebuilt-in-gitpod
|
|
||||||
9
.gitpod.Dockerfile
vendored
9
.gitpod.Dockerfile
vendored
@ -1,9 +0,0 @@
|
|||||||
FROM gitpod/workspace-full-vnc
|
|
||||||
|
|
||||||
# https://community.gitpod.io/t/long-startup-times/3299/9
|
|
||||||
ENV GITPOD_TRIGGER_REBUILD=1
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
RUN sudo apt-get update && \
|
|
||||||
sudo apt-get install -y libgtk-3-dev libsdl2-dev x11-xserver-utils parallel libfreetype-dev librlottie-dev libusb-1.0-0
|
|
||||||
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
repos:
|
|
||||||
- repo: local
|
|
||||||
hooks:
|
|
||||||
- id: codeformat
|
|
||||||
name: MicroPython codeformat.py for changed C files
|
|
||||||
entry: tools/codeformat.py -v -c -f
|
|
||||||
language: python
|
|
||||||
- id: verifygitlog
|
|
||||||
name: MicroPython git commit message format checker
|
|
||||||
entry: tools/verifygitlog.py --check-file --ignore-rebase
|
|
||||||
language: python
|
|
||||||
verbose: true
|
|
||||||
stages: [commit-msg]
|
|
||||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
|
||||||
# Version should be kept in sync with .github/workflows/ruff.yml
|
|
||||||
rev: v0.1.3
|
|
||||||
hooks:
|
|
||||||
- id: ruff
|
|
||||||
- id: ruff-format
|
|
||||||
- repo: https://github.com/codespell-project/codespell
|
|
||||||
# Version should be kept in sync with .github/workflows/codespell.yml
|
|
||||||
rev: v2.2.6
|
|
||||||
hooks:
|
|
||||||
- id: codespell
|
|
||||||
name: Spellcheck for changed files (codespell)
|
|
||||||
additional_dependencies:
|
|
||||||
- tomli
|
|
||||||
@ -11,7 +11,7 @@ It's also ok to drop file extensions.
|
|||||||
|
|
||||||
Besides prefix, first line of a commit message should describe a
|
Besides prefix, first line of a commit message should describe a
|
||||||
change clearly and to the point, and be a grammatical sentence with
|
change clearly and to the point, and be a grammatical sentence with
|
||||||
final full stop. First line must fit within 72 characters. Examples
|
final full stop. First line should fit within 72 characters. Examples
|
||||||
of good first line of commit messages:
|
of good first line of commit messages:
|
||||||
|
|
||||||
py/objstr: Add splitlines() method.
|
py/objstr: Add splitlines() method.
|
||||||
@ -27,9 +27,12 @@ change beyond 5 lines would likely require such detailed description.
|
|||||||
To get good practical examples of good commits and their messages, browse
|
To get good practical examples of good commits and their messages, browse
|
||||||
the `git log` of the project.
|
the `git log` of the project.
|
||||||
|
|
||||||
When committing you must sign-off your commit by adding "Signed-off-by:"
|
When committing you are encouraged to sign-off your commit by adding
|
||||||
line(s) at the end of the commit message, e.g. using `git commit -s`. You
|
"Signed-off-by" lines and similar, eg using "git commit -s". If you don't
|
||||||
are then certifying and signing off against the following:
|
explicitly sign-off in this way then the commit message, which includes your
|
||||||
|
name and email address in the "Author" line, implies your sign-off. In either
|
||||||
|
case, of explicit or implicit sign-off, you are certifying and signing off
|
||||||
|
against the following:
|
||||||
|
|
||||||
* That you wrote the change yourself, or took it from a project with
|
* That you wrote the change yourself, or took it from a project with
|
||||||
a compatible license (in the latter case the commit message, and possibly
|
a compatible license (in the latter case the commit message, and possibly
|
||||||
@ -46,146 +49,28 @@ are then certifying and signing off against the following:
|
|||||||
* Your contribution including commit message will be publicly and
|
* Your contribution including commit message will be publicly and
|
||||||
indefinitely available for anyone to access, including redistribution
|
indefinitely available for anyone to access, including redistribution
|
||||||
under the terms of the project's license.
|
under the terms of the project's license.
|
||||||
* Your signature for all of the above, which is the "Signed-off-by" line,
|
* Your signature for all of the above, which is the "Signed-off-by" line
|
||||||
includes your full real name and a valid and active email address by
|
or the "Author" line in the commit message, includes your full real name and
|
||||||
which you can be contacted in the foreseeable future.
|
a valid and active email address by which you can be contacted in the
|
||||||
|
foreseeable future.
|
||||||
|
|
||||||
Code auto-formatting
|
Code auto-formatting
|
||||||
====================
|
====================
|
||||||
|
|
||||||
Both C and Python code formatting are controlled for consistency across the
|
Both C and Python code are auto-formatted using the `tools/codeformat.py`
|
||||||
MicroPython codebase. C code is formatted using the `tools/codeformat.py`
|
script. This uses [uncrustify](https://github.com/uncrustify/uncrustify) to
|
||||||
script which uses [uncrustify](https://github.com/uncrustify/uncrustify).
|
format C code and [black](https://github.com/psf/black) to format Python code.
|
||||||
Python code is linted and formatted using
|
After making changes, and before committing, run this tool to reformat your
|
||||||
[ruff & ruff format](https://github.com/astral-sh/ruff).
|
changes to the correct style. Without arguments this tool will reformat all
|
||||||
After making changes, and before committing, run `tools/codeformat.py` to
|
source code (and may take some time to run). Otherwise pass as arguments to
|
||||||
reformat your C code and `ruff format` for any Python code. Without
|
the tool the files that changed and it will only reformat those.
|
||||||
arguments this tool will reformat all source code (and may take some time
|
|
||||||
to run). Otherwise pass as arguments to the tool the files that changed,
|
|
||||||
and it will only reformat those.
|
|
||||||
|
|
||||||
uncrustify
|
|
||||||
==========
|
|
||||||
|
|
||||||
Only [uncrustify](https://github.com/uncrustify/uncrustify) v0.71 or v0.72 can
|
|
||||||
be used for MicroPython. Different uncrustify versions produce slightly
|
|
||||||
different formatting, and the configuration file formats are often
|
|
||||||
incompatible. v0.73 or newer *will not work*.
|
|
||||||
|
|
||||||
Depending on your operating system version, it may be possible to install a pre-compiled
|
|
||||||
uncrustify version:
|
|
||||||
|
|
||||||
Ubuntu, Debian
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Ubuntu versions 21.10 or 22.04LTS, and Debian versions bullseye or bookworm all
|
|
||||||
include v0.72 so can be installed directly:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ apt install uncrustify
|
|
||||||
```
|
|
||||||
|
|
||||||
Arch Linux
|
|
||||||
----------
|
|
||||||
|
|
||||||
The current Arch uncrustify version is too new. There is an [old Arch package
|
|
||||||
for v0.72](https://archive.archlinux.org/packages/u/uncrustify/) that can be
|
|
||||||
installed from the Arch Linux archive ([more
|
|
||||||
information](https://wiki.archlinux.org/title/Downgrading_packages#Arch_Linux_Archive)). Use
|
|
||||||
the [IgnorePkg feature](https://wiki.archlinux.org/title/Pacman#Skip_package_from_being_upgraded)
|
|
||||||
to prevent it re-updating.
|
|
||||||
|
|
||||||
Brew
|
|
||||||
----
|
|
||||||
|
|
||||||
This command may work, please raise a new Issue if it doesn't:
|
|
||||||
|
|
||||||
```
|
|
||||||
curl -L https://github.com/Homebrew/homebrew-core/raw/2b07d8192623365078a8b855a164ebcdf81494a6/Formula/uncrustify.rb > uncrustify.rb && brew install uncrustify.rb && rm uncrustify.rb
|
|
||||||
```
|
|
||||||
|
|
||||||
Code spell checking
|
|
||||||
===================
|
|
||||||
|
|
||||||
Code spell checking is done using [codespell](https://github.com/codespell-project/codespell#codespell)
|
|
||||||
and runs in a GitHub action in CI. Codespell is configured via `pyproject.toml`
|
|
||||||
to avoid false positives. It is recommended run codespell before submitting a
|
|
||||||
PR. To simplify this, codespell is configured as a pre-commit hook and will be
|
|
||||||
installed if you run `pre-commit install` (see below).
|
|
||||||
|
|
||||||
If you want to install and run codespell manually, you can do so by running:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ pip install codespell tomli
|
|
||||||
$ codespell
|
|
||||||
```
|
|
||||||
|
|
||||||
Automatic Pre-Commit Hooks
|
|
||||||
==========================
|
|
||||||
|
|
||||||
To have code formatting and commit message conventions automatically checked,
|
|
||||||
a configuration file is provided for the [pre-commit](https://pre-commit.com/)
|
|
||||||
tool.
|
|
||||||
|
|
||||||
First install `pre-commit`, either from your system package manager or via
|
|
||||||
`pip`. When installing `pre-commit` via pip, it is recommended to use a
|
|
||||||
virtual environment. Other sources, such as Brew are also available, see
|
|
||||||
[the docs](https://pre-commit.com/index.html#install) for details.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ apt install pre-commit # Ubuntu, Debian
|
|
||||||
$ pacman -Sy python-precommit # Arch Linux
|
|
||||||
$ brew install pre-commit # Brew
|
|
||||||
$ pip install pre-commit # PyPI
|
|
||||||
```
|
|
||||||
|
|
||||||
Next, install [uncrustify (see above)](#uncrustify). Other dependencies are managed by
|
|
||||||
pre-commit automatically, but uncrustify needs to be installed and available on
|
|
||||||
the PATH.
|
|
||||||
|
|
||||||
Then, inside the MicroPython repository, register the git hooks for pre-commit
|
|
||||||
by running:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ pre-commit install --hook-type pre-commit --hook-type commit-msg
|
|
||||||
```
|
|
||||||
|
|
||||||
pre-commit will now automatically run during `git commit` for both code and
|
|
||||||
commit message formatting.
|
|
||||||
|
|
||||||
The same formatting checks will be run by CI for any Pull Request submitted to
|
|
||||||
MicroPython. Pre-commit allows you to see any failure more quickly, and in many
|
|
||||||
cases will automatically correct it in your local working copy.
|
|
||||||
|
|
||||||
To unregister `pre-commit` from your MicroPython repository, run:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ pre-commit uninstall --hook-type pre-commit --hook-type commit-msg
|
|
||||||
```
|
|
||||||
|
|
||||||
Tips:
|
|
||||||
|
|
||||||
* To skip pre-commit checks on a single commit, use `git commit -n` (for
|
|
||||||
`--no-verify`).
|
|
||||||
* To ignore the pre-commit message format check temporarily, start the commit
|
|
||||||
message subject line with "WIP" (for "Work In Progress").
|
|
||||||
|
|
||||||
Running pre-commit manually
|
|
||||||
===========================
|
|
||||||
|
|
||||||
Once pre-commit is installed as per the previous section it can be manually
|
|
||||||
run against the MicroPython python codebase to update file formatting on
|
|
||||||
demand, with either:
|
|
||||||
* `pre-commit run --all-files` to fix all files in the MicroPython codebase
|
|
||||||
* `pre-commit run --file ./path/to/my/file` to fix just one file
|
|
||||||
* `pre-commit run --file ./path/to/my/folder/*` to fix just one folder
|
|
||||||
|
|
||||||
Python code conventions
|
Python code conventions
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
Python code follows [PEP 8](https://legacy.python.org/dev/peps/pep-0008/) and
|
Python code follows [PEP 8](https://legacy.python.org/dev/peps/pep-0008/) and
|
||||||
is auto-formatted using [ruff format](https://docs.astral.sh/ruff/formatter)
|
is auto-formatted using [black](https://github.com/psf/black) with a line-length
|
||||||
with a line-length of 99 characters.
|
of 99 characters.
|
||||||
|
|
||||||
Naming conventions:
|
Naming conventions:
|
||||||
- Module names are short and all lowercase; eg pyb, stm.
|
- Module names are short and all lowercase; eg pyb, stm.
|
||||||
@ -280,7 +165,7 @@ Documentation conventions
|
|||||||
=========================
|
=========================
|
||||||
|
|
||||||
MicroPython generally follows CPython in documentation process and
|
MicroPython generally follows CPython in documentation process and
|
||||||
conventions. reStructuredText syntax is used for the documentation.
|
conventions. reStructuredText syntax is used for the documention.
|
||||||
|
|
||||||
Specific conventions/suggestions:
|
Specific conventions/suggestions:
|
||||||
|
|
||||||
|
|||||||
15
LICENSE
15
LICENSE
@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2013-2024 Damien P. George
|
Copyright (c) 2013-2021 Damien P. George
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -35,7 +35,9 @@ used during the build process and is not part of the compiled source code.
|
|||||||
|
|
||||||
/ (MIT)
|
/ (MIT)
|
||||||
/drivers
|
/drivers
|
||||||
|
/cc3000 (BSD-3-clause)
|
||||||
/cc3100 (BSD-3-clause)
|
/cc3100 (BSD-3-clause)
|
||||||
|
/wiznet5k (BSD-3-clause)
|
||||||
/lib
|
/lib
|
||||||
/asf4 (Apache-2.0)
|
/asf4 (Apache-2.0)
|
||||||
/axtls (BSD-3-clause)
|
/axtls (BSD-3-clause)
|
||||||
@ -48,31 +50,24 @@ used during the build process and is not part of the compiled source code.
|
|||||||
/cmsis (BSD-3-clause)
|
/cmsis (BSD-3-clause)
|
||||||
/crypto-algorithms (NONE)
|
/crypto-algorithms (NONE)
|
||||||
/libhydrogen (ISC)
|
/libhydrogen (ISC)
|
||||||
/libmetal (BSD-3-clause)
|
|
||||||
/littlefs (BSD-3-clause)
|
/littlefs (BSD-3-clause)
|
||||||
/lwip (BSD-3-clause)
|
/lwip (BSD-3-clause)
|
||||||
/mynewt-nimble (Apache-2.0)
|
/mynewt-nimble (Apache-2.0)
|
||||||
/nrfx (BSD-3-clause)
|
/nrfx (BSD-3-clause)
|
||||||
/nxp_driver (BSD-3-Clause)
|
/nxp_driver (BSD-3-Clause)
|
||||||
/oofatfs (BSD-1-clause)
|
/oofatfs (BSD-1-clause)
|
||||||
/open-amp (BSD-3-clause)
|
|
||||||
/pico-sdk (BSD-3-clause)
|
/pico-sdk (BSD-3-clause)
|
||||||
/re15 (BSD-3-clause)
|
/re15 (BSD-3-clause)
|
||||||
/stm32lib (BSD-3-clause)
|
/stm32lib (BSD-3-clause)
|
||||||
|
/tinytest (BSD-3-clause)
|
||||||
/tinyusb (MIT)
|
/tinyusb (MIT)
|
||||||
/uzlib (Zlib)
|
/uzlib (Zlib)
|
||||||
/wiznet5k (MIT)
|
|
||||||
/logo (uses OFL-1.1)
|
/logo (uses OFL-1.1)
|
||||||
/ports
|
/ports
|
||||||
/cc3200
|
/cc3200
|
||||||
/hal (BSD-3-clause)
|
/hal (BSD-3-clause)
|
||||||
/simplelink (BSD-3-clause)
|
/simplelink (BSD-3-clause)
|
||||||
/FreeRTOS (GPL-2.0 with FreeRTOS exception)
|
/FreeRTOS (GPL-2.0 with FreeRTOS exception)
|
||||||
/esp32
|
|
||||||
/ppp_set_auth.* (Apache-2.0)
|
|
||||||
/rp2
|
|
||||||
/mutex_extra.c (BSD-3-clause)
|
|
||||||
/clocks_extra.c (BSD-3-clause)
|
|
||||||
/stm32
|
/stm32
|
||||||
/usbd*.c (MCD-ST Liberty SW License Agreement V2)
|
/usbd*.c (MCD-ST Liberty SW License Agreement V2)
|
||||||
/stm32_it.* (MIT + BSD-3-clause)
|
/stm32_it.* (MIT + BSD-3-clause)
|
||||||
@ -82,6 +77,8 @@ used during the build process and is not part of the compiled source code.
|
|||||||
/*/stm32*.h (BSD-3-clause)
|
/*/stm32*.h (BSD-3-clause)
|
||||||
/usbdev (MCD-ST Liberty SW License Agreement V2)
|
/usbdev (MCD-ST Liberty SW License Agreement V2)
|
||||||
/usbhost (MCD-ST Liberty SW License Agreement V2)
|
/usbhost (MCD-ST Liberty SW License Agreement V2)
|
||||||
|
/teensy
|
||||||
|
/core (PJRC.COM)
|
||||||
/zephyr
|
/zephyr
|
||||||
/src (Apache-2.0)
|
/src (Apache-2.0)
|
||||||
/tools
|
/tools
|
||||||
|
|||||||
237
README-LVGL.md
237
README-LVGL.md
@ -1,237 +0,0 @@
|
|||||||
# Micropython + lvgl
|
|
||||||
|
|
||||||
**Micropython bindings to LVGL for Embedded devices, Unix and JavaScript**
|
|
||||||
|
|
||||||
[](https://github.com/lvgl/lv_micropython/actions/workflows/unix_port.yml)
|
|
||||||
[](https://github.com/lvgl/lv_micropython/actions/workflows/stm32_port.yml)
|
|
||||||
[](https://github.com/lvgl/lv_micropython/actions/workflows/ports_esp32.yml) [](https://github.com/lvgl/lv_micropython/actions/workflows/rp2_port.yml)
|
|
||||||
[](https://gitpod.io/#https://github.com/lvgl/lv_micropython)
|
|
||||||
|
|
||||||
To quickly run Micropython + LVGL from your web browser you can also use the [Online Simulator](https://sim.lvgl.io/).
|
|
||||||
|
|
||||||
**For information about Micropython lvgl bindings please refer to [lv_binding_micropython/README.md](https://github.com/lvgl/lv_binding_micropython/blob/master/README.md)**
|
|
||||||
|
|
||||||
See also [Micropython + LittlevGL](https://blog.lvgl.io/2019-02-20/micropython-bindings) blog post. (LittlevGL is LVGL's previous name.)
|
|
||||||
For questions and discussions - please use the forum: https://forum.lvgl.io/c/micropython
|
|
||||||
|
|
||||||
Original micropython README: https://github.com/micropython/micropython/blob/master/README.md
|
|
||||||
|
|
||||||
## Relationship between `lv_micropython` and `lv_binding_micropython`
|
|
||||||
|
|
||||||
Originally, `lv_micropython` was created as an example of how to use [lv_binding_micropython](https://github.com/lvgl/lv_binding_micropython) on a Micropython fork.
|
|
||||||
|
|
||||||
As such, we try to keep changes here as minimal as possible and we try to keep it in sync with Micropython upstream releases. We also try to add changes to `lv_binding_micropython` instead of to `lv_micropython`, when possible. (for example we keep all drivers in `lv_binding_micropython`, etc.)
|
|
||||||
|
|
||||||
Eventually it turned out that many people prefer using `lv_micropython` directly and only a few use it as a reference to support LVGL on their own Micropython fork.
|
|
||||||
|
|
||||||
If you are only starting with Micropython+LVGL, it's recommended that you use `lv_micropython`, while porting a Micropython fork to LVGL is for advanced users.
|
|
||||||
|
|
||||||
Actual `lv_micropython` repo is using [LVGL binding](https://github.com/lvgl/lv_binding_micropython) as MicroPython C module.
|
|
||||||
|
|
||||||
More details: https://docs.micropython.org/en/latest/develop/cmodules.html
|
|
||||||
|
|
||||||
## Build Instructions
|
|
||||||
|
|
||||||
First step is always to clone `lv_micropython` and update its submodules recursively:
|
|
||||||
|
|
||||||
```
|
|
||||||
git clone https://github.com/lvgl/lv_micropython.git
|
|
||||||
cd lv_micropython
|
|
||||||
git submodule update --init --recursive user_modules/lv_binding_micropython
|
|
||||||
```
|
|
||||||
|
|
||||||
Next step is to build the port you want to use.
|
|
||||||
|
|
||||||
Some basic build and deploy scripts are added to `scripts` folder, to easily build and deploy firmware to your device (or use unix port).
|
|
||||||
|
|
||||||
You can of course build firmwares manually with `make` commands, if build script is missing for the port or you want to override some build parameters.
|
|
||||||
|
|
||||||
### Unix (Linux) port
|
|
||||||
|
|
||||||
Using build script:
|
|
||||||
|
|
||||||
```
|
|
||||||
cd scripts
|
|
||||||
./build-unix.sh
|
|
||||||
cd ..
|
|
||||||
./ports/unix/build-lvgl/micropython
|
|
||||||
```
|
|
||||||
|
|
||||||
Manual build:
|
|
||||||
|
|
||||||
1. `sudo apt-get install build-essential libreadline-dev libffi-dev git pkg-config libsdl2-2.0-0 libsdl2-dev python3.8 parallel`
|
|
||||||
Python 3 is required, but you can install some other version of python3 instead of 3.8, if needed.
|
|
||||||
2. `git clone https://github.com/lvgl/lv_micropython.git`
|
|
||||||
3. `cd lv_micropython`
|
|
||||||
4. `git submodule update --init --recursive user_modules/lv_binding_micropython`
|
|
||||||
5. `make -C mpy-cross`
|
|
||||||
6. `make -C ports/unix submodules`
|
|
||||||
7. `make -C ports/unix`
|
|
||||||
8. `./ports/unix/build-lvgl/micropython`
|
|
||||||
|
|
||||||
## Unix (MAC OS) port
|
|
||||||
|
|
||||||
1. `brew install sdl2 pkg-config`
|
|
||||||
2. `sdl2-config --version` Get the sdl2 version
|
|
||||||
3. `git clone https://github.com/lvgl/lv_micropython.git`
|
|
||||||
4. `cd lv_micropython`
|
|
||||||
5. `git submodule update --init --recursive user_modules/lv_binding_micropython`
|
|
||||||
6. `sudo mkdir -p /usr/local/lib/`
|
|
||||||
7. `sudo cp /opt/homebrew/Cellar/sdl2/<YOUR_SDL_VERSION>/lib/libSDL2.dylib /usr/local/lib/`
|
|
||||||
8. `sudo cp -r /opt/homebrew/Cellar/sdl2/<YOUR_SDL_VERSION>/include /usr/local/`
|
|
||||||
9. `sed -i '' 's/ -Werror//' ports/unix/Makefile mpy-cross/Makefile` Remove -Werror from compiler parameters as Mac fails compilation otherwise
|
|
||||||
10. `make -C mpy-cross`
|
|
||||||
11. `make -C ports/unix submodules`
|
|
||||||
12. `make -C ports/unix VARIANT=lvgl`
|
|
||||||
13. `./ports/unix/build-lvgl/micropython`
|
|
||||||
|
|
||||||
### ESP32 port
|
|
||||||
|
|
||||||
Install ESP-IDF v5.x: https://docs.espressif.com/projects/esp-idf/en/v5.2.3/esp32/get-started/index.html#manual-installation
|
|
||||||
|
|
||||||
(you can configure ESP-IDF path in [scripts/env-variables-esp32.sh](./scripts/env-variables-esp32.sh) file)
|
|
||||||
|
|
||||||
Build and deploy with scripts:
|
|
||||||
|
|
||||||
```
|
|
||||||
cd scripts
|
|
||||||
./build-esp32.sh
|
|
||||||
./deploy-esp32.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Manual build:
|
|
||||||
|
|
||||||
Please run `esp-idf/export.sh` from your ESP-IDF installation directory as explained in the [Micropython ESP32 Getting Started documentation](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/#get-started-export)
|
|
||||||
ESP-IDF version needs to match Micropython expected esp-idf, otherwise a warning will be displayed (and build will probably fail)
|
|
||||||
For more details refer to [Setting up the toolchain and ESP-IDF](https://github.com/lvgl/lv_micropython/blob/master/ports/esp32/README.md#setting-up-the-toolchain-and-esp-idf)
|
|
||||||
|
|
||||||
When using IL9341 driver, the color depth need to be set to match ILI9341. This can be done from the command line.
|
|
||||||
Here is the command to build ESP32 + LVGL which is compatible with ILI9341 driver:
|
|
||||||
|
|
||||||
```
|
|
||||||
make -C mpy-cross
|
|
||||||
make -C ports/esp32 LV_CFLAGS="-DLV_COLOR_DEPTH=16" BOARD=ESP32_GENERIC BOARD_VARIANT=SPIRAM deploy
|
|
||||||
```
|
|
||||||
|
|
||||||
Explanation about the parameters:
|
|
||||||
- `LV_CFLAGS` are used to override color depth, for ILI9341 compatibility.
|
|
||||||
- `LV_COLOR_DEPTH=16` is needed if you plan to use the ILI9341 driver.
|
|
||||||
- `BOARD` - I use WROVER board with SPIRAM. You can choose other boards from `ports/esp32/boards/` directory.
|
|
||||||
- `deploy` - make command will create ESP32 port of Micropython, and will try to deploy it through USB-UART bridge.
|
|
||||||
|
|
||||||
For more details please refer to [Micropython ESP32 README](https://github.com/micropython/micropython/blob/master/ports/esp32/README.md).
|
|
||||||
|
|
||||||
### JavaScript port
|
|
||||||
|
|
||||||
Refer to the README of the `lvgl_javascript` branch: https://github.com/lvgl/lv_micropython/tree/lvgl_javascript_v8#javascript-port
|
|
||||||
|
|
||||||
### Raspberry Pi Pico port
|
|
||||||
|
|
||||||
This port uses [Micropython infrastructure for C modules](https://docs.micropython.org/en/latest/develop/cmodules.html#compiling-the-cmodule-into-micropython) and `USER_C_MODULES` must be given:
|
|
||||||
|
|
||||||
1. `git clone https://github.com/lvgl/lv_micropython.git`
|
|
||||||
2. `cd lv_micropython`
|
|
||||||
3. `git submodule update --init --recursive user_modules/lv_binding_micropython`
|
|
||||||
4. `make -C ports/rp2 BOARD=PICO submodules`
|
|
||||||
5. `make -j -C mpy-cross`
|
|
||||||
6. `make -j -C ports/rp2 BOARD=PICO USER_C_MODULES=../../user_modules/lv_binding_micropython/bindings.cmake`
|
|
||||||
|
|
||||||
#### Troubleshooting
|
|
||||||
|
|
||||||
If you experience unstable behaviour, it is worth checking the value of *MICROPY_HW_FLASH_STORAGE_BASE* against the value of *__flash_binary_end* from the firmware.elf.map file.
|
|
||||||
If the storage base is lower than the binary end, parts of the firmware will be overwritten when the micropython filesystem is initialised.
|
|
||||||
|
|
||||||
## Super Simple Example
|
|
||||||
|
|
||||||
First, LVGL needs to be imported and initialized
|
|
||||||
|
|
||||||
```python
|
|
||||||
import lvgl as lv
|
|
||||||
lv.init()
|
|
||||||
```
|
|
||||||
|
|
||||||
Then event loop, display driver and input driver needs to be registered.
|
|
||||||
Refer to [Porting the library](https://docs.lvgl.io/8.0/porting/index.html) for more information.
|
|
||||||
Here is an example of registering SDL drivers on Micropython unix port:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Create an event loop and Register SDL display/mouse/keyboard drivers.
|
|
||||||
from lv_utils import event_loop
|
|
||||||
|
|
||||||
WIDTH = 480
|
|
||||||
HEIGHT = 320
|
|
||||||
|
|
||||||
event_loop = event_loop()
|
|
||||||
disp_drv = lv.sdl_window_create(WIDTH, HEIGHT)
|
|
||||||
disp_drv.set_default()
|
|
||||||
display = lv.display_get_default()
|
|
||||||
|
|
||||||
group = lv.group_create()
|
|
||||||
group.set_default()
|
|
||||||
|
|
||||||
mouse = lv.sdl_mouse_create()
|
|
||||||
mouse.set_display(display)
|
|
||||||
mouse.set_group(group)
|
|
||||||
|
|
||||||
keyboard = lv.sdl_keyboard_create()
|
|
||||||
keyboard.set_display(display)
|
|
||||||
keyboard.set_group(group)
|
|
||||||
```
|
|
||||||
|
|
||||||
Here is an alternative example, for registering ILI9341 drivers on Micropython ESP32 port:
|
|
||||||
|
|
||||||
```python
|
|
||||||
import lvgl as lv
|
|
||||||
|
|
||||||
# Import ILI9341 driver and initialized it
|
|
||||||
|
|
||||||
from ili9341 import ili9341
|
|
||||||
disp = ili9341()
|
|
||||||
|
|
||||||
# Import XPT2046 driver and initialize it
|
|
||||||
|
|
||||||
from xpt2046 import xpt2046
|
|
||||||
touch = xpt2046()
|
|
||||||
```
|
|
||||||
|
|
||||||
By default, both ILI9341 and XPT2046 are initialized on the same SPI bus with the following parameters:
|
|
||||||
|
|
||||||
- ILI9341: `miso=5, mosi=18, clk=19, cs=13, dc=12, rst=4, power=14, backlight=15, spihost=esp.HSPI_HOST, mhz=40, factor=4, hybrid=True`
|
|
||||||
- XPT2046: `cs=25, spihost=esp.HSPI_HOST, mhz=5, max_cmds=16, cal_x0 = 3783, cal_y0 = 3948, cal_x1 = 242, cal_y1 = 423, transpose = True, samples = 3`
|
|
||||||
|
|
||||||
You can change any of these parameters on ili9341/xpt2046 constructor.
|
|
||||||
You can also initialize them on different SPI buses if you want, by providing miso/mosi/clk parameters. Set them to -1 to use existing (initialized) spihost bus.
|
|
||||||
|
|
||||||
Now you can create the GUI itself:
|
|
||||||
|
|
||||||
```python
|
|
||||||
|
|
||||||
# Create a screen with a button and a label
|
|
||||||
|
|
||||||
scr = lv.obj()
|
|
||||||
btn = lv.button(scr)
|
|
||||||
btn.align_to(lv.scr_act(), lv.ALIGN.CENTER, 0, 0)
|
|
||||||
label = lv.label(btn)
|
|
||||||
label.set_text("Hello World!")
|
|
||||||
|
|
||||||
# Load the screen
|
|
||||||
|
|
||||||
lv.screen_load(scr)
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## More information
|
|
||||||
|
|
||||||
More info about LVGL:
|
|
||||||
- Website https://lvgl.io
|
|
||||||
- GitHub: https://github.com/lvgl/lvgl
|
|
||||||
- Documentation: https://docs.lvgl.io/master/get-started/bindings/micropython.html
|
|
||||||
- Examples: https://docs.lvgl.io/master/examples.html
|
|
||||||
- More examples: https://github.com/lvgl/lv_binding_micropython/tree/master/examples
|
|
||||||
|
|
||||||
More info about lvgl Micropython bindings:
|
|
||||||
- https://github.com/lvgl/lv_binding_micropython/blob/master/README.md
|
|
||||||
|
|
||||||
Discussions about the Micropython binding: https://github.com/lvgl/lvgl/issues/557
|
|
||||||
|
|
||||||
More info about the unix port: https://github.com/micropython/micropython/wiki/Getting-Started#debian-ubuntu-mint-and-variants
|
|
||||||
275
README.md
275
README.md
@ -1,10 +1,4 @@
|
|||||||
# Micropython + LVGL
|
[](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [](https://codecov.io/gh/micropython/micropython)
|
||||||
|
|
||||||
**Micropython bindings to LVGL for Embedded devices, Unix and JavaScript**
|
|
||||||
|
|
||||||
More information about MicroPython-LVGL binding and how to build it, see: [README-LVGL.md](README-LVGL.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
The MicroPython project
|
The MicroPython project
|
||||||
=======================
|
=======================
|
||||||
@ -21,43 +15,167 @@ code-base, including project-wide name changes and API changes.
|
|||||||
|
|
||||||
MicroPython implements the entire Python 3.4 syntax (including exceptions,
|
MicroPython implements the entire Python 3.4 syntax (including exceptions,
|
||||||
`with`, `yield from`, etc., and additionally `async`/`await` keywords from
|
`with`, `yield from`, etc., and additionally `async`/`await` keywords from
|
||||||
Python 3.5 and some select features from later versions). The following core
|
Python 3.5). The following core datatypes are provided: `str` (including
|
||||||
datatypes are provided: `str`(including basic Unicode support), `bytes`,
|
basic Unicode support), `bytes`, `bytearray`, `tuple`, `list`, `dict`, `set`,
|
||||||
`bytearray`, `tuple`, `list`, `dict`, `set`, `frozenset`, `array.array`,
|
`frozenset`, `array.array`, `collections.namedtuple`, classes and instances.
|
||||||
`collections.namedtuple`, classes and instances. Builtin modules include
|
Builtin modules include `sys`, `time`, and `struct`, etc. Select ports have
|
||||||
`os`, `sys`, `time`, `re`, and `struct`, etc. Some ports have support for
|
support for `_thread` module (multithreading). Note that only a subset of
|
||||||
`_thread` module (multithreading), `socket` and `ssl` for networking, and
|
Python 3 functionality is implemented for the data types and modules.
|
||||||
`asyncio`. Note that only a subset of Python 3 functionality is implemented
|
|
||||||
for the data types and modules.
|
|
||||||
|
|
||||||
MicroPython can execute scripts in textual source form (.py files) or from
|
MicroPython can execute scripts in textual source form or from precompiled
|
||||||
precompiled bytecode (.mpy files), in both cases either from an on-device
|
bytecode, in both cases either from an on-device filesystem or "frozen" into
|
||||||
filesystem or "frozen" into the MicroPython executable.
|
the MicroPython executable.
|
||||||
|
|
||||||
MicroPython also provides a set of MicroPython-specific modules to access
|
See the repository http://github.com/micropython/pyboard for the MicroPython
|
||||||
hardware-specific functionality and peripherals such as GPIO, Timers, ADC,
|
board (PyBoard), the officially supported reference electronic circuit board.
|
||||||
DAC, PWM, SPI, I2C, CAN, Bluetooth, and USB.
|
|
||||||
|
|
||||||
Getting started
|
Major components in this repository:
|
||||||
---------------
|
- py/ -- the core Python implementation, including compiler, runtime, and
|
||||||
|
core library.
|
||||||
|
- mpy-cross/ -- the MicroPython cross-compiler which is used to turn scripts
|
||||||
|
into precompiled bytecode.
|
||||||
|
- ports/unix/ -- a version of MicroPython that runs on Unix.
|
||||||
|
- ports/stm32/ -- a version of MicroPython that runs on the PyBoard and similar
|
||||||
|
STM32 boards (using ST's Cube HAL drivers).
|
||||||
|
- ports/minimal/ -- a minimal MicroPython port. Start with this if you want
|
||||||
|
to port MicroPython to another microcontroller.
|
||||||
|
- tests/ -- test framework and test scripts.
|
||||||
|
- docs/ -- user documentation in Sphinx reStructuredText format. Rendered
|
||||||
|
HTML documentation is available at http://docs.micropython.org.
|
||||||
|
|
||||||
See the [online documentation](https://docs.micropython.org/) for the API
|
Additional components:
|
||||||
reference and information about using MicroPython and information about how
|
- ports/bare-arm/ -- a bare minimum version of MicroPython for ARM MCUs. Used
|
||||||
it is implemented.
|
mostly to control code size.
|
||||||
|
- ports/teensy/ -- a version of MicroPython that runs on the Teensy 3.1
|
||||||
|
(preliminary but functional).
|
||||||
|
- ports/pic16bit/ -- a version of MicroPython for 16-bit PIC microcontrollers.
|
||||||
|
- ports/cc3200/ -- a version of MicroPython that runs on the CC3200 from TI.
|
||||||
|
- ports/esp8266/ -- a version of MicroPython that runs on Espressif's ESP8266 SoC.
|
||||||
|
- ports/esp32/ -- a version of MicroPython that runs on Espressif's ESP32 SoC.
|
||||||
|
- ports/nrf/ -- a version of MicroPython that runs on Nordic's nRF51 and nRF52 MCUs.
|
||||||
|
- extmod/ -- additional (non-core) modules implemented in C.
|
||||||
|
- tools/ -- various tools, including the pyboard.py module.
|
||||||
|
- examples/ -- a few example Python scripts.
|
||||||
|
|
||||||
We use [GitHub Discussions](https://github.com/micropython/micropython/discussions)
|
The subdirectories above may include READMEs with additional info.
|
||||||
as our forum, and [Discord](https://discord.gg/RB8HZSAExQ) for chat. These
|
|
||||||
are great places to ask questions and advice from the community or to discuss your
|
|
||||||
MicroPython-based projects.
|
|
||||||
|
|
||||||
For bugs and feature requests, please [raise an issue](https://github.com/micropython/micropython/issues/new/choose)
|
"make" is used to build the components, or "gmake" on BSD-based systems.
|
||||||
and follow the templates there.
|
You will also need bash, gcc, and Python 3.3+ available as the command `python3`
|
||||||
|
(if your system only has Python 2.7 then invoke make with the additional option
|
||||||
|
`PYTHON=python2`).
|
||||||
|
|
||||||
For information about the [MicroPython pyboard](https://store.micropython.org/pyb-features),
|
The MicroPython cross-compiler, mpy-cross
|
||||||
the officially supported board from the
|
-----------------------------------------
|
||||||
[original Kickstarter campaign](https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers),
|
|
||||||
see the [schematics and pinouts](http://github.com/micropython/pyboard) and
|
Most ports require the MicroPython cross-compiler to be built first. This
|
||||||
[documentation](https://docs.micropython.org/en/latest/pyboard/quickref.html).
|
program, called mpy-cross, is used to pre-compile Python scripts to .mpy
|
||||||
|
files which can then be included (frozen) into the firmware/executable for
|
||||||
|
a port. To build mpy-cross use:
|
||||||
|
|
||||||
|
$ cd mpy-cross
|
||||||
|
$ make
|
||||||
|
|
||||||
|
The Unix version
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The "unix" port requires a standard Unix environment with gcc and GNU make.
|
||||||
|
x86 and x64 architectures are supported (i.e. x86 32- and 64-bit), as well
|
||||||
|
as ARM and MIPS. Making full-featured port to another architecture requires
|
||||||
|
writing some assembly code for the exception handling and garbage collection.
|
||||||
|
Alternatively, fallback implementation based on setjmp/longjmp can be used.
|
||||||
|
|
||||||
|
To build (see section below for required dependencies):
|
||||||
|
|
||||||
|
$ cd ports/unix
|
||||||
|
$ make submodules
|
||||||
|
$ make
|
||||||
|
|
||||||
|
Then to give it a try:
|
||||||
|
|
||||||
|
$ ./micropython
|
||||||
|
>>> list(5 * x + y for x in range(10) for y in [4, 2, 1])
|
||||||
|
|
||||||
|
Use `CTRL-D` (i.e. EOF) to exit the shell.
|
||||||
|
Learn about command-line options (in particular, how to increase heap size
|
||||||
|
which may be needed for larger applications):
|
||||||
|
|
||||||
|
$ ./micropython -h
|
||||||
|
|
||||||
|
Run complete testsuite:
|
||||||
|
|
||||||
|
$ make test
|
||||||
|
|
||||||
|
Unix version comes with a builtin package manager called upip, e.g.:
|
||||||
|
|
||||||
|
$ ./micropython -m upip install micropython-pystone
|
||||||
|
$ ./micropython -m pystone
|
||||||
|
|
||||||
|
Browse available modules on
|
||||||
|
[PyPI](https://pypi.python.org/pypi?%3Aaction=search&term=micropython).
|
||||||
|
Standard library modules come from
|
||||||
|
[micropython-lib](https://github.com/micropython/micropython-lib) project.
|
||||||
|
|
||||||
|
External dependencies
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Building MicroPython ports may require some dependencies installed.
|
||||||
|
|
||||||
|
For Unix port, `libffi` library and `pkg-config` tool are required. On
|
||||||
|
Debian/Ubuntu/Mint derivative Linux distros, install `build-essential`
|
||||||
|
(includes toolchain and make), `libffi-dev`, and `pkg-config` packages.
|
||||||
|
|
||||||
|
Other dependencies can be built together with MicroPython. This may
|
||||||
|
be required to enable extra features or capabilities, and in recent
|
||||||
|
versions of MicroPython, these may be enabled by default. To build
|
||||||
|
these additional dependencies, in the port directory you're
|
||||||
|
interested in (e.g. `ports/unix/`) first execute:
|
||||||
|
|
||||||
|
$ make submodules
|
||||||
|
|
||||||
|
This will fetch all the relevant git submodules (sub repositories) that
|
||||||
|
the port needs. Use the same command to get the latest versions of
|
||||||
|
submodules as they are updated from time to time. After that execute:
|
||||||
|
|
||||||
|
$ make deplibs
|
||||||
|
|
||||||
|
This will build all available dependencies (regardless whether they
|
||||||
|
are used or not). If you intend to build MicroPython with additional
|
||||||
|
options (like cross-compiling), the same set of options should be passed
|
||||||
|
to `make deplibs`. To actually enable/disable use of dependencies, edit
|
||||||
|
`ports/unix/mpconfigport.mk` file, which has inline descriptions of the options.
|
||||||
|
For example, to build SSL module (required for `upip` tool described above,
|
||||||
|
and so enabled by default), `MICROPY_PY_USSL` should be set to 1.
|
||||||
|
|
||||||
|
For some ports, building required dependences is transparent, and happens
|
||||||
|
automatically. But they still need to be fetched with the `make submodules`
|
||||||
|
command.
|
||||||
|
|
||||||
|
The STM32 version
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
The "stm32" port requires an ARM compiler, arm-none-eabi-gcc, and associated
|
||||||
|
bin-utils. For those using Arch Linux, you need arm-none-eabi-binutils,
|
||||||
|
arm-none-eabi-gcc and arm-none-eabi-newlib packages. Otherwise, try here:
|
||||||
|
https://launchpad.net/gcc-arm-embedded
|
||||||
|
|
||||||
|
To build:
|
||||||
|
|
||||||
|
$ cd ports/stm32
|
||||||
|
$ make submodules
|
||||||
|
$ make
|
||||||
|
|
||||||
|
You then need to get your board into DFU mode. On the pyboard, connect the
|
||||||
|
3V3 pin to the P1/DFU pin with a wire (on PYBv1.0 they are next to each other
|
||||||
|
on the bottom left of the board, second row from the bottom).
|
||||||
|
|
||||||
|
Then to flash the code via USB DFU to your device:
|
||||||
|
|
||||||
|
$ make deploy
|
||||||
|
|
||||||
|
This will use the included `tools/pydfu.py` script. If flashing the firmware
|
||||||
|
does not work it may be because you don't have the correct permissions, and
|
||||||
|
need to use `sudo make deploy`.
|
||||||
|
See the README.md file in the ports/stm32/ directory for further details.
|
||||||
|
|
||||||
Contributing
|
Contributing
|
||||||
------------
|
------------
|
||||||
@ -68,86 +186,3 @@ productive, please be sure to follow the
|
|||||||
and the [Code Conventions](https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md).
|
and the [Code Conventions](https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md).
|
||||||
Note that MicroPython is licenced under the MIT license, and all contributions
|
Note that MicroPython is licenced under the MIT license, and all contributions
|
||||||
should follow this license.
|
should follow this license.
|
||||||
|
|
||||||
About this repository
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
This repository contains the following components:
|
|
||||||
- [py/](py/) -- the core Python implementation, including compiler, runtime, and
|
|
||||||
core library.
|
|
||||||
- [mpy-cross/](mpy-cross/) -- the MicroPython cross-compiler which is used to turn scripts
|
|
||||||
into precompiled bytecode.
|
|
||||||
- [ports/](ports/) -- platform-specific code for the various ports and architectures that MicroPython runs on.
|
|
||||||
- [lib/](lib/) -- submodules for external dependencies.
|
|
||||||
- [tests/](tests/) -- test framework and test scripts.
|
|
||||||
- [docs/](docs/) -- user documentation in Sphinx reStructuredText format. This is used to generate the [online documentation](http://docs.micropython.org).
|
|
||||||
- [extmod/](extmod/) -- additional (non-core) modules implemented in C.
|
|
||||||
- [tools/](tools/) -- various tools, including the pyboard.py module.
|
|
||||||
- [examples/](examples/) -- a few example Python scripts.
|
|
||||||
|
|
||||||
"make" is used to build the components, or "gmake" on BSD-based systems.
|
|
||||||
You will also need bash, gcc, and Python 3.3+ available as the command `python3`
|
|
||||||
(if your system only has Python 2.7 then invoke make with the additional option
|
|
||||||
`PYTHON=python2`). Some ports (rp2 and esp32) additionally use CMake.
|
|
||||||
|
|
||||||
Supported platforms & architectures
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
MicroPython runs on a wide range of microcontrollers, as well as on Unix-like
|
|
||||||
(including Linux, BSD, macOS, WSL) and Windows systems.
|
|
||||||
|
|
||||||
Microcontroller targets can be as small as 256kiB flash + 16kiB RAM, although
|
|
||||||
devices with at least 512kiB flash + 128kiB RAM allow a much more
|
|
||||||
full-featured experience.
|
|
||||||
|
|
||||||
The [Unix](ports/unix) and [Windows](ports/windows) ports allow both
|
|
||||||
development and testing of MicroPython itself, as well as providing
|
|
||||||
lightweight alternative to CPython on these platforms (in particular on
|
|
||||||
embedded Linux systems).
|
|
||||||
|
|
||||||
The ["minimal"](ports/minimal) port provides an example of a very basic
|
|
||||||
MicroPython port and can be compiled as both a standalone Linux binary as
|
|
||||||
well as for ARM Cortex M4. Start with this if you want to port MicroPython to
|
|
||||||
another microcontroller. Additionally the ["bare-arm"](ports/bare-arm) port
|
|
||||||
is an example of the absolute minimum configuration, and is used to keep
|
|
||||||
track of the code size of the core runtime and VM.
|
|
||||||
|
|
||||||
In addition, the following ports are provided in this repository:
|
|
||||||
- [cc3200](ports/cc3200) -- Texas Instruments CC3200 (including PyCom WiPy).
|
|
||||||
- [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3, ESP32C6).
|
|
||||||
- [esp8266](ports/esp8266) -- Espressif ESP8266 SoC.
|
|
||||||
- [mimxrt](ports/mimxrt) -- NXP m.iMX RT (including Teensy 4.x).
|
|
||||||
- [nrf](ports/nrf) -- Nordic Semiconductor nRF51 and nRF52.
|
|
||||||
- [pic16bit](ports/pic16bit) -- Microchip PIC 16-bit.
|
|
||||||
- [powerpc](ports/powerpc) -- IBM PowerPC (including Microwatt)
|
|
||||||
- [qemu](ports/qemu) -- QEMU-based emulated target (for testing)
|
|
||||||
- [renesas-ra](ports/renesas-ra) -- Renesas RA family.
|
|
||||||
- [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W).
|
|
||||||
- [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51.
|
|
||||||
- [stm32](ports/stm32) -- STMicroelectronics STM32 family (including F0, F4, F7, G0, G4, H7, L0, L4, WB)
|
|
||||||
- [webassembly](ports/webassembly) -- Emscripten port targeting browsers and NodeJS.
|
|
||||||
- [zephyr](ports/zephyr) -- Zephyr RTOS.
|
|
||||||
|
|
||||||
The MicroPython cross-compiler, mpy-cross
|
|
||||||
-----------------------------------------
|
|
||||||
|
|
||||||
Most ports require the [MicroPython cross-compiler](mpy-cross) to be built
|
|
||||||
first. This program, called mpy-cross, is used to pre-compile Python scripts
|
|
||||||
to .mpy files which can then be included (frozen) into the
|
|
||||||
firmware/executable for a port. To build mpy-cross use:
|
|
||||||
|
|
||||||
$ cd mpy-cross
|
|
||||||
$ make
|
|
||||||
|
|
||||||
External dependencies
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
The core MicroPython VM and runtime has no external dependencies, but a given
|
|
||||||
port might depend on third-party drivers or vendor HALs. This repository
|
|
||||||
includes [several submodules](lib/) linking to these external dependencies.
|
|
||||||
Before compiling a given port, use
|
|
||||||
|
|
||||||
$ cd ports/name
|
|
||||||
$ make submodules
|
|
||||||
|
|
||||||
to ensure that all required submodules are initialised.
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
# You can set these variables from the command line.
|
# You can set these variables from the command line.
|
||||||
PYTHON = python3
|
PYTHON = python3
|
||||||
SPHINXOPTS = -W --keep-going -j auto
|
SPHINXOPTS = -W --keep-going
|
||||||
SPHINXBUILD = sphinx-build
|
SPHINXBUILD = sphinx-build
|
||||||
PAPER =
|
PAPER =
|
||||||
BUILDDIR = build/$(MICROPY_PORT)
|
BUILDDIR = build/$(MICROPY_PORT)
|
||||||
|
|||||||
@ -47,7 +47,7 @@ This can be achieved with:
|
|||||||
|
|
||||||
make latexpdf
|
make latexpdf
|
||||||
|
|
||||||
but requires a rather complete install of LaTeX with various extensions. On
|
but require rather complete install of LaTeX with various extensions. On
|
||||||
Debian/Ubuntu, try (1GB+ download):
|
Debian/Ubuntu, try (500MB+ download):
|
||||||
|
|
||||||
apt install texlive-latex-recommended texlive-latex-extra texlive-xetex texlive-fonts-extra cm-super xindy
|
apt-get install texlive-latex-recommended texlive-latex-extra
|
||||||
|
|||||||
199
docs/conf.py
199
docs/conf.py
@ -19,56 +19,54 @@ import os
|
|||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
sys.path.insert(0, os.path.abspath("."))
|
sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
# The MICROPY_VERSION env var should be "vX.Y.Z" (or unset).
|
|
||||||
micropy_version = os.getenv("MICROPY_VERSION") or "latest"
|
|
||||||
micropy_all_versions = (os.getenv("MICROPY_ALL_VERSIONS") or "latest").split(",")
|
|
||||||
url_pattern = "%s/en/%%s" % (os.getenv("MICROPY_URL_PREFIX") or "/",)
|
|
||||||
|
|
||||||
# The members of the html_context dict are available inside topindex.html
|
# The members of the html_context dict are available inside topindex.html
|
||||||
|
micropy_version = os.getenv('MICROPY_VERSION') or 'latest'
|
||||||
|
micropy_all_versions = (os.getenv('MICROPY_ALL_VERSIONS') or 'latest').split(',')
|
||||||
|
url_pattern = '%s/en/%%s' % (os.getenv('MICROPY_URL_PREFIX') or '/',)
|
||||||
html_context = {
|
html_context = {
|
||||||
"cur_version": micropy_version,
|
'cur_version':micropy_version,
|
||||||
"all_versions": [(ver, url_pattern % ver) for ver in micropy_all_versions],
|
'all_versions':[
|
||||||
"downloads": [
|
(ver, url_pattern % ver) for ver in micropy_all_versions
|
||||||
("PDF", url_pattern % micropy_version + "/micropython-docs.pdf"),
|
],
|
||||||
|
'downloads':[
|
||||||
|
('PDF', url_pattern % micropy_version + '/micropython-docs.pdf'),
|
||||||
],
|
],
|
||||||
"is_release": micropy_version != "latest",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# -- General configuration ------------------------------------------------
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
# needs_sphinx = '1.0'
|
#needs_sphinx = '1.0'
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
# ones.
|
# ones.
|
||||||
extensions = [
|
extensions = [
|
||||||
"sphinx.ext.autodoc",
|
'sphinx.ext.autodoc',
|
||||||
"sphinx.ext.doctest",
|
'sphinx.ext.doctest',
|
||||||
"sphinx.ext.intersphinx",
|
'sphinx.ext.intersphinx',
|
||||||
"sphinx.ext.todo",
|
'sphinx.ext.todo',
|
||||||
"sphinx.ext.coverage",
|
'sphinx.ext.coverage',
|
||||||
"sphinxcontrib.jquery",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
templates_path = ["templates"]
|
templates_path = ['templates']
|
||||||
|
|
||||||
# The suffix of source filenames.
|
# The suffix of source filenames.
|
||||||
source_suffix = ".rst"
|
source_suffix = '.rst'
|
||||||
|
|
||||||
# The encoding of source files.
|
# The encoding of source files.
|
||||||
# source_encoding = 'utf-8-sig'
|
#source_encoding = 'utf-8-sig'
|
||||||
|
|
||||||
# The master toctree document.
|
# The master toctree document.
|
||||||
master_doc = "index"
|
master_doc = 'index'
|
||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = "MicroPython"
|
project = 'MicroPython'
|
||||||
copyright = "- The MicroPython Documentation is Copyright © 2014-2024, Damien P. George, Paul Sokolovsky, and contributors"
|
copyright = '- The MicroPython Documentation is Copyright © 2014-2021, Damien P. George, Paul Sokolovsky, and contributors'
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# |version| and |release|, also used in various other places throughout the
|
||||||
@ -76,45 +74,45 @@ copyright = "- The MicroPython Documentation is Copyright © 2014-2024, Damien P
|
|||||||
#
|
#
|
||||||
# We don't follow "The short X.Y version" vs "The full version, including alpha/beta/rc tags"
|
# We don't follow "The short X.Y version" vs "The full version, including alpha/beta/rc tags"
|
||||||
# breakdown, so use the same version identifier for both to avoid confusion.
|
# breakdown, so use the same version identifier for both to avoid confusion.
|
||||||
version = release = micropy_version
|
version = release = '1.17'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
# language = None
|
#language = None
|
||||||
|
|
||||||
# There are two options for replacing |today|: either, you set today to some
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
# non-false value, then it is used:
|
# non-false value, then it is used:
|
||||||
# today = ''
|
#today = ''
|
||||||
# Else, today_fmt is used as the format for a strftime call.
|
# Else, today_fmt is used as the format for a strftime call.
|
||||||
# today_fmt = '%B %d, %Y'
|
#today_fmt = '%B %d, %Y'
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
# List of patterns, relative to source directory, that match files and
|
||||||
# directories to ignore when looking for source files.
|
# directories to ignore when looking for source files.
|
||||||
exclude_patterns = ["build", ".venv"]
|
exclude_patterns = ['build', '.venv']
|
||||||
|
|
||||||
# The reST default role (used for this markup: `text`) to use for all
|
# The reST default role (used for this markup: `text`) to use for all
|
||||||
# documents.
|
# documents.
|
||||||
default_role = "any"
|
default_role = 'any'
|
||||||
|
|
||||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
# add_function_parentheses = True
|
#add_function_parentheses = True
|
||||||
|
|
||||||
# If true, the current module name will be prepended to all description
|
# If true, the current module name will be prepended to all description
|
||||||
# unit titles (such as .. function::).
|
# unit titles (such as .. function::).
|
||||||
# add_module_names = True
|
#add_module_names = True
|
||||||
|
|
||||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||||
# output. They are ignored by default.
|
# output. They are ignored by default.
|
||||||
# show_authors = False
|
#show_authors = False
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
pygments_style = "sphinx"
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
# A list of ignored prefixes for module index sorting.
|
# A list of ignored prefixes for module index sorting.
|
||||||
# modindex_common_prefix = []
|
#modindex_common_prefix = []
|
||||||
|
|
||||||
# If true, keep warnings as "system message" paragraphs in the built documents.
|
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||||
# keep_warnings = False
|
#keep_warnings = False
|
||||||
|
|
||||||
# Global include files. Sphinx docs suggest using rst_epilog in preference
|
# Global include files. Sphinx docs suggest using rst_epilog in preference
|
||||||
# of rst_prolog, so we follow. Absolute paths below mean "from the base
|
# of rst_prolog, so we follow. Absolute paths below mean "from the base
|
||||||
@ -126,168 +124,153 @@ rst_epilog = """
|
|||||||
# -- Options for HTML output ----------------------------------------------
|
# -- Options for HTML output ----------------------------------------------
|
||||||
|
|
||||||
# on_rtd is whether we are on readthedocs.org
|
# on_rtd is whether we are on readthedocs.org
|
||||||
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
|
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||||
|
|
||||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||||
try:
|
try:
|
||||||
import sphinx_rtd_theme
|
import sphinx_rtd_theme
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
html_theme = "sphinx_rtd_theme"
|
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
|
||||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
|
|
||||||
except:
|
except:
|
||||||
html_theme = "default"
|
html_theme = 'default'
|
||||||
html_theme_path = ["."]
|
html_theme_path = ['.']
|
||||||
else:
|
else:
|
||||||
html_theme_path = ["."]
|
html_theme_path = ['.']
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
# further. For a list of options available for each theme, see the
|
# further. For a list of options available for each theme, see the
|
||||||
# documentation.
|
# documentation.
|
||||||
# html_theme_options = {}
|
#html_theme_options = {}
|
||||||
|
|
||||||
# Add any paths that contain custom themes here, relative to this directory.
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
# html_theme_path = ['.']
|
# html_theme_path = ['.']
|
||||||
|
|
||||||
# The name for this set of Sphinx documents. If None, it defaults to
|
# The name for this set of Sphinx documents. If None, it defaults to
|
||||||
# "<project> v<release> documentation".
|
# "<project> v<release> documentation".
|
||||||
# html_title = None
|
#html_title = None
|
||||||
|
|
||||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||||
# html_short_title = None
|
#html_short_title = None
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top
|
# The name of an image file (relative to this directory) to place at the top
|
||||||
# of the sidebar.
|
# of the sidebar.
|
||||||
# html_logo = '../../logo/trans-logo.png'
|
#html_logo = '../../logo/trans-logo.png'
|
||||||
|
|
||||||
# The name of an image file (within the static path) to use as favicon of the
|
# The name of an image file (within the static path) to use as favicon of the
|
||||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||||
# pixels large.
|
# pixels large.
|
||||||
html_favicon = "static/favicon.ico"
|
html_favicon = 'static/favicon.ico'
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
html_static_path = ["static"]
|
html_static_path = ['static']
|
||||||
|
|
||||||
# Add a custom CSS file for HTML generation
|
|
||||||
html_css_files = [
|
|
||||||
"custom.css",
|
|
||||||
]
|
|
||||||
# Add any extra paths that contain custom files (such as robots.txt or
|
# Add any extra paths that contain custom files (such as robots.txt or
|
||||||
# .htaccess) here, relative to this directory. These files are copied
|
# .htaccess) here, relative to this directory. These files are copied
|
||||||
# directly to the root of the documentation.
|
# directly to the root of the documentation.
|
||||||
# html_extra_path = []
|
#html_extra_path = []
|
||||||
|
|
||||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||||
# using the given strftime format.
|
# using the given strftime format.
|
||||||
html_last_updated_fmt = "%d %b %Y"
|
html_last_updated_fmt = '%d %b %Y'
|
||||||
|
|
||||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
# typographically correct entities.
|
# typographically correct entities.
|
||||||
# html_use_smartypants = True
|
#html_use_smartypants = True
|
||||||
|
|
||||||
# Custom sidebar templates, maps document names to template names.
|
# Custom sidebar templates, maps document names to template names.
|
||||||
# html_sidebars = {}
|
#html_sidebars = {}
|
||||||
|
|
||||||
# Additional templates that should be rendered to pages, maps page names to
|
# Additional templates that should be rendered to pages, maps page names to
|
||||||
# template names.
|
# template names.
|
||||||
html_additional_pages = {"index": "topindex.html"}
|
html_additional_pages = {"index": "topindex.html"}
|
||||||
|
|
||||||
# If false, no module index is generated.
|
# If false, no module index is generated.
|
||||||
# html_domain_indices = True
|
#html_domain_indices = True
|
||||||
|
|
||||||
# If false, no index is generated.
|
# If false, no index is generated.
|
||||||
# html_use_index = True
|
#html_use_index = True
|
||||||
|
|
||||||
# If true, the index is split into individual pages for each letter.
|
# If true, the index is split into individual pages for each letter.
|
||||||
# html_split_index = False
|
#html_split_index = False
|
||||||
|
|
||||||
# If true, links to the reST sources are added to the pages.
|
# If true, links to the reST sources are added to the pages.
|
||||||
# html_show_sourcelink = True
|
#html_show_sourcelink = True
|
||||||
|
|
||||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||||
# html_show_sphinx = True
|
#html_show_sphinx = True
|
||||||
|
|
||||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||||
# html_show_copyright = True
|
#html_show_copyright = True
|
||||||
|
|
||||||
# If true, an OpenSearch description file will be output, and all pages will
|
# If true, an OpenSearch description file will be output, and all pages will
|
||||||
# contain a <link> tag referring to it. The value of this option must be the
|
# contain a <link> tag referring to it. The value of this option must be the
|
||||||
# base URL from which the finished HTML is served.
|
# base URL from which the finished HTML is served.
|
||||||
# html_use_opensearch = ''
|
#html_use_opensearch = ''
|
||||||
|
|
||||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||||
# html_file_suffix = None
|
#html_file_suffix = None
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
# Output file base name for HTML help builder.
|
||||||
htmlhelp_basename = "MicroPythondoc"
|
htmlhelp_basename = 'MicroPythondoc'
|
||||||
|
|
||||||
|
|
||||||
# -- Options for LaTeX output ---------------------------------------------
|
# -- Options for LaTeX output ---------------------------------------------
|
||||||
|
|
||||||
latex_elements = {
|
latex_elements = {
|
||||||
# The paper size ('letterpaper' or 'a4paper').
|
# The paper size ('letterpaper' or 'a4paper').
|
||||||
#'papersize': 'letterpaper',
|
#'papersize': 'letterpaper',
|
||||||
# The font size ('10pt', '11pt' or '12pt').
|
|
||||||
#'pointsize': '10pt',
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
# Additional stuff for the LaTeX preamble.
|
#'pointsize': '10pt',
|
||||||
#'preamble': '',
|
|
||||||
# Include 3 levels of headers in PDF ToC
|
# Additional stuff for the LaTeX preamble.
|
||||||
"preamble": r"\setcounter{tocdepth}{2}",
|
#'preamble': '',
|
||||||
|
# Include 3 levels of headers in PDF ToC
|
||||||
|
'preamble': '\setcounter{tocdepth}{2}',
|
||||||
}
|
}
|
||||||
|
|
||||||
# Grouping the document tree into LaTeX files. List of tuples
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
# (source start file, target name, title,
|
# (source start file, target name, title,
|
||||||
# author, documentclass [howto, manual, or own class]).
|
# author, documentclass [howto, manual, or own class]).
|
||||||
latex_documents = [
|
latex_documents = [
|
||||||
(
|
(master_doc, 'MicroPython.tex', 'MicroPython Documentation',
|
||||||
master_doc,
|
'Damien P. George, Paul Sokolovsky, and contributors', 'manual'),
|
||||||
"MicroPython.tex",
|
|
||||||
"MicroPython Documentation",
|
|
||||||
"Damien P. George, Paul Sokolovsky, and contributors",
|
|
||||||
"manual",
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top of
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
# the title page.
|
# the title page.
|
||||||
# latex_logo = None
|
#latex_logo = None
|
||||||
|
|
||||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||||
# not chapters.
|
# not chapters.
|
||||||
# latex_use_parts = False
|
#latex_use_parts = False
|
||||||
|
|
||||||
# If true, show page references after internal links.
|
# If true, show page references after internal links.
|
||||||
# latex_show_pagerefs = False
|
#latex_show_pagerefs = False
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
# If true, show URL addresses after external links.
|
||||||
# latex_show_urls = False
|
#latex_show_urls = False
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
# Documents to append as an appendix to all manuals.
|
||||||
# latex_appendices = []
|
#latex_appendices = []
|
||||||
|
|
||||||
# If false, no module index is generated.
|
# If false, no module index is generated.
|
||||||
# latex_domain_indices = True
|
#latex_domain_indices = True
|
||||||
|
|
||||||
# Enable better Unicode support so that `make latexpdf` doesn't fail
|
|
||||||
latex_engine = "xelatex"
|
|
||||||
|
|
||||||
# -- Options for manual page output ---------------------------------------
|
# -- Options for manual page output ---------------------------------------
|
||||||
|
|
||||||
# One entry per manual page. List of tuples
|
# One entry per manual page. List of tuples
|
||||||
# (source start file, name, description, authors, manual section).
|
# (source start file, name, description, authors, manual section).
|
||||||
man_pages = [
|
man_pages = [
|
||||||
(
|
('index', 'micropython', 'MicroPython Documentation',
|
||||||
"index",
|
['Damien P. George, Paul Sokolovsky, and contributors'], 1),
|
||||||
"micropython",
|
|
||||||
"MicroPython Documentation",
|
|
||||||
["Damien P. George, Paul Sokolovsky, and contributors"],
|
|
||||||
1,
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
# If true, show URL addresses after external links.
|
||||||
# man_show_urls = False
|
#man_show_urls = False
|
||||||
|
|
||||||
|
|
||||||
# -- Options for Texinfo output -------------------------------------------
|
# -- Options for Texinfo output -------------------------------------------
|
||||||
@ -296,29 +279,23 @@ man_pages = [
|
|||||||
# (source start file, target name, title, author,
|
# (source start file, target name, title, author,
|
||||||
# dir menu entry, description, category)
|
# dir menu entry, description, category)
|
||||||
texinfo_documents = [
|
texinfo_documents = [
|
||||||
(
|
(master_doc, 'MicroPython', 'MicroPython Documentation',
|
||||||
master_doc,
|
'Damien P. George, Paul Sokolovsky, and contributors', 'MicroPython', 'One line description of project.',
|
||||||
"MicroPython",
|
'Miscellaneous'),
|
||||||
"MicroPython Documentation",
|
|
||||||
"Damien P. George, Paul Sokolovsky, and contributors",
|
|
||||||
"MicroPython",
|
|
||||||
"One line description of project.",
|
|
||||||
"Miscellaneous",
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
# Documents to append as an appendix to all manuals.
|
||||||
# texinfo_appendices = []
|
#texinfo_appendices = []
|
||||||
|
|
||||||
# If false, no module index is generated.
|
# If false, no module index is generated.
|
||||||
# texinfo_domain_indices = True
|
#texinfo_domain_indices = True
|
||||||
|
|
||||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||||
# texinfo_show_urls = 'footnote'
|
#texinfo_show_urls = 'footnote'
|
||||||
|
|
||||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||||
# texinfo_no_detailmenu = False
|
#texinfo_no_detailmenu = False
|
||||||
|
|
||||||
|
|
||||||
# Example configuration for intersphinx: refer to the Python standard library.
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
intersphinx_mapping = {"python": ("https://docs.python.org/3.5", None)}
|
intersphinx_mapping = {'python': ('https://docs.python.org/3.5', None)}
|
||||||
|
|||||||
@ -49,17 +49,9 @@ A MicroPython user C module is a directory with the following files:
|
|||||||
in your ``micropython.mk`` to a local make variable,
|
in your ``micropython.mk`` to a local make variable,
|
||||||
eg ``EXAMPLE_MOD_DIR := $(USERMOD_DIR)``
|
eg ``EXAMPLE_MOD_DIR := $(USERMOD_DIR)``
|
||||||
|
|
||||||
Your ``micropython.mk`` must add your modules source files to the
|
Your ``micropython.mk`` must add your modules source files relative to your
|
||||||
``SRC_USERMOD_C`` or ``SRC_USERMOD_LIB_C`` variables. The former will be
|
expanded copy of ``$(USERMOD_DIR)`` to ``SRC_USERMOD``, eg
|
||||||
processed for ``MP_QSTR_`` and ``MP_REGISTER_MODULE`` definitions, the latter
|
``SRC_USERMOD += $(EXAMPLE_MOD_DIR)/example.c``
|
||||||
will not (e.g. helpers and library code that isn't MicroPython-specific).
|
|
||||||
These paths should include your expanded copy of ``$(USERMOD_DIR)``, e.g.::
|
|
||||||
|
|
||||||
SRC_USERMOD_C += $(EXAMPLE_MOD_DIR)/modexample.c
|
|
||||||
SRC_USERMOD_LIB_C += $(EXAMPLE_MOD_DIR)/utils/algorithm.c
|
|
||||||
|
|
||||||
Similarly, use ``SRC_USERMOD_CXX`` and ``SRC_USERMOD_LIB_CXX`` for C++
|
|
||||||
source files. If you want to include assembly files use ``SRC_USERMOD_LIB_ASM``.
|
|
||||||
|
|
||||||
If you have custom compiler options (like ``-I`` to add directories to search
|
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
|
for header files), these should be added to ``CFLAGS_USERMOD`` for C code
|
||||||
@ -95,12 +87,9 @@ A MicroPython user C module is a directory with the following files:
|
|||||||
Basic example
|
Basic example
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
The ``cexample`` module provides examples for a function and a class. The
|
This simple module named ``cexample`` provides a single function
|
||||||
``cexample.add_ints(a, b)`` function adds two integer args together and returns
|
``cexample.add_ints(a, b)`` which adds the two integer args together and returns
|
||||||
the result. The ``cexample.Timer()`` type creates timers that can be used to
|
the result. It can be found in the MicroPython source tree
|
||||||
measure the elapsed time since the object is instantiated.
|
|
||||||
|
|
||||||
The module can be found in the MicroPython source tree
|
|
||||||
`in the examples directory <https://github.com/micropython/micropython/tree/master/examples/usercmodule/cexample>`_
|
`in the examples directory <https://github.com/micropython/micropython/tree/master/examples/usercmodule/cexample>`_
|
||||||
and has a source file and a Makefile fragment with content as described above::
|
and has a source file and a Makefile fragment with content as described above::
|
||||||
|
|
||||||
@ -232,25 +221,23 @@ as described above.
|
|||||||
If a module is not enabled by default then the corresponding C preprocessor macro
|
If a module is not enabled by default then the corresponding C preprocessor macro
|
||||||
must be enabled. This macro name can be found by searching for the ``MP_REGISTER_MODULE``
|
must be enabled. This macro name can be found by searching for the ``MP_REGISTER_MODULE``
|
||||||
line in the module's source code (it usually appears at the end of the main source file).
|
line in the module's source code (it usually appears at the end of the main source file).
|
||||||
This macro should be surrounded by a ``#if X`` / ``#endif`` pair, and the configuration
|
The third argument to ``MP_REGISTER_MODULE`` is the macro name, and this must be set
|
||||||
option ``X`` must be set to 1 using ``CFLAGS_EXTRA`` to make the module available. If
|
to 1 using ``CFLAGS_EXTRA`` to make the module available. If the third argument is just
|
||||||
there is no ``#if X`` / ``#endif`` pair then the module is enabled by default.
|
the number 1 then the module is enabled by default.
|
||||||
|
|
||||||
For example, the ``examples/usercmodule/cexample`` module is enabled by default so
|
For example, the ``examples/usercmodule/cexample`` module is enabled by default so
|
||||||
has the following line in its source code:
|
has the following line in its source code:
|
||||||
|
|
||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
|
||||||
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule);
|
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, 1);
|
||||||
|
|
||||||
Alternatively, to make this module disabled by default but selectable through
|
Alternatively, to make this module disabled by default but selectable through
|
||||||
a preprocessor configuration option, it would be:
|
a preprocessor configuration option, it would be:
|
||||||
|
|
||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
|
||||||
#if MODULE_CEXAMPLE_ENABLED
|
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, MODULE_CEXAMPLE_ENABLED);
|
||||||
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
In this case the module is enabled by adding ``CFLAGS_EXTRA=-DMODULE_CEXAMPLE_ENABLED=1``
|
In this case the module is enabled by adding ``CFLAGS_EXTRA=-DMODULE_CEXAMPLE_ENABLED=1``
|
||||||
to the ``make`` command, or editing ``mpconfigport.h`` or ``mpconfigboard.h`` to add
|
to the ``make`` command, or editing ``mpconfigport.h`` or ``mpconfigboard.h`` to add
|
||||||
@ -275,13 +262,3 @@ can now be accessed in Python just like any other builtin module, e.g.
|
|||||||
import cexample
|
import cexample
|
||||||
print(cexample.add_ints(1, 3))
|
print(cexample.add_ints(1, 3))
|
||||||
# should display 4
|
# should display 4
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from cexample import Timer
|
|
||||||
from time import sleep_ms
|
|
||||||
|
|
||||||
watch = Timer()
|
|
||||||
sleep_ms(1000)
|
|
||||||
print(watch.time())
|
|
||||||
# should display approximately 1000
|
|
||||||
|
|||||||
@ -98,7 +98,7 @@ Then also edit ``py/lexer.c`` to add the new keyword literal text:
|
|||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
:emphasize-lines: 12
|
:emphasize-lines: 12
|
||||||
|
|
||||||
static const char *const tok_kw[] = {
|
STATIC const char *const tok_kw[] = {
|
||||||
...
|
...
|
||||||
"or",
|
"or",
|
||||||
"pass",
|
"pass",
|
||||||
@ -147,17 +147,10 @@ The most relevant method you should know about is this:
|
|||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
|
||||||
mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl) {
|
mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl) {
|
||||||
// Create a context for this module, and set its globals dict.
|
|
||||||
mp_module_context_t *context = m_new_obj(mp_module_context_t);
|
|
||||||
context->module.globals = mp_globals_get();
|
|
||||||
|
|
||||||
// Compile the input parse_tree to a raw-code structure.
|
// Compile the input parse_tree to a raw-code structure.
|
||||||
mp_compiled_module_t cm;
|
mp_raw_code_t *rc = mp_compile_to_raw_code(parse_tree, source_file, is_repl);
|
||||||
cm.context = context;
|
|
||||||
mp_compile_to_raw_code(parse_tree, source_file, is_repl, &cm);
|
|
||||||
|
|
||||||
// Create and return a function object that executes the outer module.
|
// 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(rc, MP_OBJ_NULL, MP_OBJ_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
The compiler compiles the code in four passes: scope, stack size, code size and emit.
|
The compiler compiles the code in four passes: scope, stack size, code size and emit.
|
||||||
@ -301,7 +294,7 @@ code statement:
|
|||||||
|
|
||||||
.. code-block:: c
|
.. 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;
|
vtype_kind_t vtype;
|
||||||
emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
|
emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
|
||||||
if (vtype == VTYPE_PYOBJ) {
|
if (vtype == VTYPE_PYOBJ) {
|
||||||
|
|||||||
@ -16,3 +16,4 @@ live in the main MicroPython repository.
|
|||||||
|
|
||||||
cmodules.rst
|
cmodules.rst
|
||||||
natmod.rst
|
natmod.rst
|
||||||
|
|
||||||
@ -100,10 +100,10 @@ For the stm32 port, the ARM cross-compiler is required:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ sudo apt-get install gcc-arm-none-eabi libnewlib-arm-none-eabi
|
$ sudo apt-get install arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib
|
||||||
|
|
||||||
See the `ARM GCC
|
See the `ARM GCC
|
||||||
toolchain <https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads>`_
|
toolchain <https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm>`_
|
||||||
for the latest details.
|
for the latest details.
|
||||||
|
|
||||||
Python is also required. Python 2 is supported for now, but we recommend using Python 3.
|
Python is also required. Python 2 is supported for now, but we recommend using Python 3.
|
||||||
@ -228,7 +228,7 @@ You can also specify which board to use:
|
|||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ cd ports/stm32
|
$ cd ports/stm32
|
||||||
$ make BOARD=<board> submodules
|
$ make submodules
|
||||||
$ make BOARD=<board>
|
$ make BOARD=<board>
|
||||||
|
|
||||||
See `ports/stm32/boards <https://github.com/micropython/micropython/tree/master/ports/stm32/boards>`_
|
See `ports/stm32/boards <https://github.com/micropython/micropython/tree/master/ports/stm32/boards>`_
|
||||||
@ -245,7 +245,7 @@ that you use a virtual environment:
|
|||||||
|
|
||||||
$ python3 -m venv env
|
$ python3 -m venv env
|
||||||
$ source env/bin/activate
|
$ source env/bin/activate
|
||||||
$ pip install -r docs/requirements.txt
|
$ pip install sphinx
|
||||||
|
|
||||||
Navigate to the ``docs`` directory:
|
Navigate to the ``docs`` directory:
|
||||||
|
|
||||||
@ -322,8 +322,7 @@ tests
|
|||||||
|
|
||||||
tools
|
tools
|
||||||
|
|
||||||
Contains scripts used by the build and CI process, as well as user tools such
|
Contains helper tools including the ``upip`` and the ``pyboard.py`` module.
|
||||||
as ``pyboard.py`` and ``mpremote``.
|
|
||||||
|
|
||||||
examples
|
examples
|
||||||
|
|
||||||
|
|||||||
@ -24,3 +24,4 @@ MicroPython to a new platform and implementing a core MicroPython library.
|
|||||||
publiccapi.rst
|
publiccapi.rst
|
||||||
extendingmicropython.rst
|
extendingmicropython.rst
|
||||||
porting.rst
|
porting.rst
|
||||||
|
|
||||||
@ -48,23 +48,23 @@ hypothetical new module ``subsystem`` in the file ``modsubsystem.c``:
|
|||||||
#if MICROPY_PY_SUBSYSTEM
|
#if MICROPY_PY_SUBSYSTEM
|
||||||
|
|
||||||
// info()
|
// info()
|
||||||
static mp_obj_t py_subsystem_info(void) {
|
STATIC mp_obj_t py_subsystem_info(void) {
|
||||||
return MP_OBJ_NEW_SMALL_INT(42);
|
return MP_OBJ_NEW_SMALL_INT(42);
|
||||||
}
|
}
|
||||||
MP_DEFINE_CONST_FUN_OBJ_0(subsystem_info_obj, py_subsystem_info);
|
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___name__), MP_ROM_QSTR(MP_QSTR_subsystem) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&subsystem_info_obj) },
|
{ 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 = {
|
const mp_obj_module_t mp_module_subsystem = {
|
||||||
.base = { &mp_type_module },
|
.base = { &mp_type_module },
|
||||||
.globals = (mp_obj_dict_t *)&mp_module_subsystem_globals,
|
.globals = (mp_obj_dict_t *)&mp_module_subsystem_globals,
|
||||||
};
|
};
|
||||||
|
|
||||||
MP_REGISTER_MODULE(MP_QSTR_subsystem, mp_module_subsystem);
|
MP_REGISTER_MODULE(MP_QSTR_subsystem, mp_module_subsystem, MICROPY_PY_SUBSYSTEM);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,6 @@ options for the ``ARCH`` variable, see below):
|
|||||||
|
|
||||||
* ``x86`` (32 bit)
|
* ``x86`` (32 bit)
|
||||||
* ``x64`` (64 bit x86)
|
* ``x64`` (64 bit x86)
|
||||||
* ``armv6m`` (ARM Thumb, eg Cortex-M0)
|
|
||||||
* ``armv7m`` (ARM Thumb 2, eg Cortex-M3)
|
* ``armv7m`` (ARM Thumb 2, eg Cortex-M3)
|
||||||
* ``armv7emsp`` (ARM Thumb 2, single precision float, eg Cortex-M4F, Cortex-M7)
|
* ``armv7emsp`` (ARM Thumb 2, single precision float, eg Cortex-M4F, Cortex-M7)
|
||||||
* ``armv7emdp`` (ARM Thumb 2, double precision float, eg Cortex-M7)
|
* ``armv7emdp`` (ARM Thumb 2, double precision float, eg Cortex-M7)
|
||||||
@ -128,7 +127,7 @@ The file ``factorial.c`` contains:
|
|||||||
#include "py/dynruntime.h"
|
#include "py/dynruntime.h"
|
||||||
|
|
||||||
// Helper function to compute factorial
|
// 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) {
|
if (x == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -136,7 +135,7 @@ The file ``factorial.c`` contains:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is the function which will be called from Python, as factorial(x)
|
// 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
|
// Extract the integer from the MicroPython input object
|
||||||
mp_int_t x = mp_obj_get_int(x_obj);
|
mp_int_t x = mp_obj_get_int(x_obj);
|
||||||
// Calculate the factorial
|
// Calculate the factorial
|
||||||
@ -145,7 +144,7 @@ The file ``factorial.c`` contains:
|
|||||||
return mp_obj_new_int(result);
|
return mp_obj_new_int(result);
|
||||||
}
|
}
|
||||||
// Define a Python reference to the function above
|
// 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
|
// 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) {
|
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||||
@ -172,7 +171,7 @@ The file ``Makefile`` contains:
|
|||||||
# Source files (.c or .py)
|
# Source files (.c or .py)
|
||||||
SRC = factorial.c
|
SRC = factorial.c
|
||||||
|
|
||||||
# Architecture to build for (x86, x64, armv6m, armv7m, xtensa, xtensawin)
|
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||||
ARCH = x64
|
ARCH = x64
|
||||||
|
|
||||||
# Include to get the rules for compiling and linking the module
|
# Include to get the rules for compiling and linking the module
|
||||||
|
|||||||
@ -25,15 +25,13 @@ into the firmware image as part of the main firmware compilation process, which
|
|||||||
the bytecode will be executed from ROM. This can lead to a significant memory saving, and
|
the bytecode will be executed from ROM. This can lead to a significant memory saving, and
|
||||||
reduce heap fragmentation.
|
reduce heap fragmentation.
|
||||||
|
|
||||||
See :ref:`manifest` for more information.
|
|
||||||
|
|
||||||
Variables
|
Variables
|
||||||
---------
|
---------
|
||||||
|
|
||||||
MicroPython processes local and global variables differently. Global 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
|
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).
|
(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
|
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.
|
within the Python stack, which is more efficient than a global lookup in a dict.
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,6 @@ The basic MicroPython firmware is implemented in the main port file, e.g ``main.
|
|||||||
|
|
||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
|
||||||
#include "py/builtin.h"
|
|
||||||
#include "py/compile.h"
|
#include "py/compile.h"
|
||||||
#include "py/gc.h"
|
#include "py/gc.h"
|
||||||
#include "py/mperrno.h"
|
#include "py/mperrno.h"
|
||||||
@ -54,6 +53,8 @@ The basic MicroPython firmware is implemented in the main port file, e.g ``main.
|
|||||||
mp_stack_ctrl_init();
|
mp_stack_ctrl_init();
|
||||||
gc_init(heap, heap + sizeof(heap));
|
gc_init(heap, heap + sizeof(heap));
|
||||||
mp_init();
|
mp_init();
|
||||||
|
mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), 0);
|
||||||
|
mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0);
|
||||||
|
|
||||||
// Start a normal REPL; will exit when ctrl-D is entered on a blank line.
|
// Start a normal REPL; will exit when ctrl-D is entered on a blank line.
|
||||||
pyexec_friendly_repl();
|
pyexec_friendly_repl();
|
||||||
@ -83,7 +84,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.
|
// 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);
|
mp_raise_OSError(MP_ENOENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,11 +97,10 @@ We also need a Makefile at this point for the port:
|
|||||||
|
|
||||||
# Include py core make definitions.
|
# Include py core make definitions.
|
||||||
include $(TOP)/py/py.mk
|
include $(TOP)/py/py.mk
|
||||||
include $(TOP)/extmod/extmod.mk
|
|
||||||
|
|
||||||
# Set CFLAGS and libraries.
|
# Set CFLAGS and libraries.
|
||||||
CFLAGS += -I. -I$(BUILD) -I$(TOP)
|
CFLAGS = -I. -I$(BUILD) -I$(TOP)
|
||||||
LIBS += -lm
|
LIBS = -lm
|
||||||
|
|
||||||
# Define the required source files.
|
# Define the required source files.
|
||||||
SRC_C = \
|
SRC_C = \
|
||||||
@ -111,9 +111,6 @@ We also need a Makefile at this point for the port:
|
|||||||
shared/runtime/pyexec.c \
|
shared/runtime/pyexec.c \
|
||||||
shared/runtime/stdout_helpers.c \
|
shared/runtime/stdout_helpers.c \
|
||||||
|
|
||||||
# Define source files containung qstrs.
|
|
||||||
SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c
|
|
||||||
|
|
||||||
# Define the required object files.
|
# Define the required object files.
|
||||||
OBJ = $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
OBJ = $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
||||||
|
|
||||||
@ -175,6 +172,9 @@ The following is an example of an ``mpconfigport.h`` file:
|
|||||||
|
|
||||||
#define MP_STATE_PORT MP_STATE_VM
|
#define MP_STATE_PORT MP_STATE_VM
|
||||||
|
|
||||||
|
#define MICROPY_PORT_ROOT_POINTERS \
|
||||||
|
const char *readline_hist[8];
|
||||||
|
|
||||||
This configuration file contains machine-specific configurations including aspects like if different
|
This configuration file contains machine-specific configurations including aspects like if different
|
||||||
MicroPython features should be enabled e.g. ``#define MICROPY_ENABLE_GC (1)``. Making this Setting
|
MicroPython features should be enabled e.g. ``#define MICROPY_ENABLE_GC (1)``. Making this Setting
|
||||||
``(0)`` disables the feature.
|
``(0)`` disables the feature.
|
||||||
@ -262,24 +262,29 @@ To add a custom module like ``myport``, first add the module definition in a fil
|
|||||||
|
|
||||||
#include "py/runtime.h"
|
#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");
|
mp_printf(&mp_plat_print, "info about my port\n");
|
||||||
return mp_const_none;
|
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_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) },
|
{ 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 = {
|
const mp_obj_module_t myport_module = {
|
||||||
.base = { &mp_type_module },
|
.base = { &mp_type_module },
|
||||||
.globals = (mp_obj_dict_t *)&myport_module_globals,
|
.globals = (mp_obj_dict_t *)&myport_module_globals,
|
||||||
};
|
};
|
||||||
|
|
||||||
MP_REGISTER_MODULE(MP_QSTR_myport, myport_module);
|
MP_REGISTER_MODULE(MP_QSTR_myport, myport_module, 1);
|
||||||
|
|
||||||
|
Note: the "1" as the third argument in ``MP_REGISTER_MODULE`` enables this new module
|
||||||
|
unconditionally. To allow it to be conditionally enabled, replace the "1" by
|
||||||
|
``MICROPY_PY_MYPORT`` and then add ``#define MICROPY_PY_MYPORT (1)`` in ``mpconfigport.h``
|
||||||
|
accordingly.
|
||||||
|
|
||||||
You will also need to edit the Makefile to add ``modmyport.c`` to the ``SRC_C`` list, and
|
You will also need to edit the Makefile to add ``modmyport.c`` to the ``SRC_C`` list, and
|
||||||
a new line adding the same file to ``SRC_QSTR`` (so qstrs are searched for in this new file),
|
a new line adding the same file to ``SRC_QSTR`` (so qstrs are searched for in this new file),
|
||||||
@ -293,7 +298,7 @@ like this:
|
|||||||
mphalport.c \
|
mphalport.c \
|
||||||
...
|
...
|
||||||
|
|
||||||
SRC_QSTR += modmyport.c
|
SRC_QSTR += modport.c
|
||||||
|
|
||||||
If all went correctly then, after rebuilding, you should be able to import the new module:
|
If all went correctly then, after rebuilding, you should be able to import the new module:
|
||||||
|
|
||||||
|
|||||||
@ -3,22 +3,8 @@
|
|||||||
MicroPython differences from CPython
|
MicroPython differences from CPython
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
MicroPython implements Python 3.4 and some select features of Python 3.5 and
|
The operations listed in this section produce conflicting results in MicroPython when compared to standard Python.
|
||||||
above. The sections below describe the current status of these features.
|
MicroPython implements Python 3.4 and some select features of Python 3.5.
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
../differences/python_35.rst
|
|
||||||
../differences/python_36.rst
|
|
||||||
../differences/python_37.rst
|
|
||||||
../differences/python_38.rst
|
|
||||||
../differences/python_39.rst
|
|
||||||
../differences/python_310.rst
|
|
||||||
|
|
||||||
For the features of Python that are implemented by MicroPython, there are
|
|
||||||
sometimes differences in their behaviour compared to standard Python. The
|
|
||||||
operations listed in the sections below produce conflicting results in
|
|
||||||
MicroPython when compared to standard Python.
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|||||||
@ -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)
|
|
||||||
@ -1,238 +0,0 @@
|
|||||||
.. _python_310:
|
|
||||||
|
|
||||||
Python 3.10
|
|
||||||
===========
|
|
||||||
|
|
||||||
Python 3.10.0 (final) was released on the 4 October 2021. The Features for 3.10 are
|
|
||||||
defined in `PEP 619 <https://www.python.org/dev/peps/pep-0619/#features-for-3-10>`_
|
|
||||||
and a detailed description of the changes can be found in
|
|
||||||
`What's New in Python 3.10 <https://docs.python.org/3/whatsnew/3.10.html>`_.
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 20 60 20
|
|
||||||
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| **New syntax features** | **Status** |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| `PEP 634 <https://www.python.org/dev/peps/pep-0634/>`_ | Structural Pattern Matching: Specification | [#spm]_ |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| `PEP 635 <https://www.python.org/dev/peps/pep-0635/>`_ | Structural Pattern Matching: Motivation and | [#spm]_ |
|
|
||||||
| | Rationale | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| `PEP 636 <https://www.python.org/dev/peps/pep-0636/>`_ | Structural Pattern Matching: Tutorial | [#spm]_ |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| `bpo-12782 | Parenthesized context managers are now officially | |
|
|
||||||
| <https://github.com/python/cpython/issues/56991>`_ | allowed | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| **New features in the standard library** |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| `PEP 618 <https://www.python.org/dev/peps/pep-0618/>`_ | Add Optional Length-Checking To zip | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| **Interpreter improvements** |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| `PEP 626 <https://www.python.org/dev/peps/pep-0626/>`_ | Precise line numbers for debugging and other tools | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| **New typing features** |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| `PEP 604 <https://www.python.org/dev/peps/pep-0604/>`_ | Allow writing union types as X | Y | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| `PEP 613 <https://www.python.org/dev/peps/pep-0613/>`_ | Explicit Type Aliases | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| `PEP 612 <https://www.python.org/dev/peps/pep-0612/>`_ | Parameter Specification Variables | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| **Important deprecations, removals or restrictions** |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| `PEP 644 <https://www.python.org/dev/peps/pep-0644/>`_ | Require OpenSSL 1.1.1 or newer | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| `PEP 632 <https://www.python.org/dev/peps/pep-0632/>`_ | Deprecate distutils module. | Not relevant |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| `PEP 623 <https://www.python.org/dev/peps/pep-0623/>`_ | Deprecate and prepare for the removal of the wstr | Not relevant |
|
|
||||||
| | member in PyUnicodeObject. | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| `PEP 624 <https://www.python.org/dev/peps/pep-0624/>`_ | Remove Py_UNICODE encoder APIs | Not relevant |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
| `PEP 597 <https://www.python.org/dev/peps/pep-0597/>`_ | Add optional EncodingWarning | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+--------------+
|
|
||||||
|
|
||||||
|
|
||||||
Other Language Changes:
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 90 10
|
|
||||||
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The :class:`int` type has a new method :meth:`int.bit_count`, returning the | |
|
|
||||||
| number of ones in the binary expansion of a given integer, also known | |
|
|
||||||
| as the population count. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The views returned by :meth:`dict.keys`, :meth:`dict.values` and | |
|
|
||||||
| :meth:`dict.items` now all have a ``mapping`` attribute that gives a | |
|
|
||||||
| :class:`types.MappingProxyType` object wrapping the original | |
|
|
||||||
| dictionary. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| :pep:`618`: The :func:`zip` function now has an optional ``strict`` flag, used | |
|
|
||||||
| to require that all the iterables have an equal length. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Builtin and extension functions that take integer arguments no longer accept | |
|
|
||||||
| :class:`~decimal.Decimal`\ s, :class:`~fractions.Fraction`\ s and other | |
|
|
||||||
| objects that can be converted to integers only with a loss (e.g. that have | |
|
|
||||||
| the :meth:`~object.__int__` method but do not have the | |
|
|
||||||
| :meth:`~object.__index__` method). | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| If :func:`object.__ipow__` returns :const:`NotImplemented`, the operator will | |
|
|
||||||
| correctly fall back to :func:`object.__pow__` and :func:`object.__rpow__` as expected. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Assignment expressions can now be used unparenthesized within set literals | |
|
|
||||||
| and set comprehensions, as well as in sequence indexes (but not slices). | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Functions have a new ``__builtins__`` attribute which is used to look for | |
|
|
||||||
| builtin symbols when a function is executed, instead of looking into | |
|
|
||||||
| ``__globals__['__builtins__']``. The attribute is initialized from | |
|
|
||||||
| ``__globals__["__builtins__"]`` if it exists, else from the current builtins. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Two new builtin functions -- :func:`aiter` and :func:`anext` have been added | |
|
|
||||||
| to provide asynchronous counterparts to :func:`iter` and :func:`next`, | |
|
|
||||||
| respectively. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Static methods (:func:`@staticmethod <staticmethod>`) and class methods | |
|
|
||||||
| (:func:`@classmethod <classmethod>`) now inherit the method attributes | |
|
|
||||||
| (``__module__``, ``__name__``, ``__qualname__``, ``__doc__``, | |
|
|
||||||
| ``__annotations__``) and have a new ``__wrapped__`` attribute. | |
|
|
||||||
| Moreover, static methods are now callable as regular functions. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Annotations for complex targets (everything beside ``simple name`` targets | |
|
|
||||||
| defined by :pep:`526`) no longer cause any runtime effects with ``from __future__ import annotations``. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Class and module objects now lazy-create empty annotations dicts on demand. | |
|
|
||||||
| The annotations dicts are stored in the object’s ``__dict__`` for | |
|
|
||||||
| backwards compatibility. This improves the best practices for working | |
|
|
||||||
| with ``__annotations__``. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Annotations consist of ``yield``, ``yield from``, ``await`` or named expressions | |
|
|
||||||
| are now forbidden under ``from __future__ import annotations`` due to their side | |
|
|
||||||
| effects. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Usage of unbound variables, ``super()`` and other expressions that might | |
|
|
||||||
| alter the processing of symbol table as annotations are now rendered | |
|
|
||||||
| effectless under ``from __future__ import annotations``. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Hashes of NaN values of both :class:`float` type and | |
|
|
||||||
| :class:`decimal.Decimal` type now depend on object identity. Formerly, they | |
|
|
||||||
| always hashed to ``0`` even though NaN values are not equal to one another. | |
|
|
||||||
| This caused potentially quadratic runtime behavior due to excessive hash | |
|
|
||||||
| collisions when creating dictionaries and sets containing multiple NaNs. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| A :exc:`SyntaxError` (instead of a :exc:`NameError`) will be raised when deleting | |
|
|
||||||
| the :const:`__debug__` constant. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| :exc:`SyntaxError` exceptions now have ``end_lineno`` and | |
|
|
||||||
| ``end_offset`` attributes. They will be ``None`` if not determined. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
|
|
||||||
Changes to built-in modules:
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 90 10
|
|
||||||
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `asyncio <https://docs.python.org/3/whatsnew/3.10.html#asyncio>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Add missing :meth:`~asyncio.events.AbstractEventLoop.connect_accepted_socket` | |
|
|
||||||
| method. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `array <https://docs.python.org/3/whatsnew/3.10.html#array>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The :meth:`~array.array.index` method of :class:`array.array` now has | |
|
|
||||||
| optional *start* and *stop* parameters. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `gc <https://docs.python.org/3/whatsnew/3.10.html#gc>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Add audit hooks for :func:`gc.get_objects`, :func:`gc.get_referrers` and | |
|
|
||||||
| :func:`gc.get_referents`. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `hashlib <https://docs.python.org/3/whatsnew/3.10.html#hashlib>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The hashlib module requires OpenSSL 1.1.1 or newer. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The hashlib module has preliminary support for OpenSSL 3.0.0. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The pure-Python fallback of :func:`~hashlib.pbkdf2_hmac` is deprecated. In | |
|
|
||||||
| the future PBKDF2-HMAC will only be available when Python has been built with | |
|
|
||||||
| OpenSSL support. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `os <https://docs.python.org/3/whatsnew/3.10.html#os>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Add :func:`os.cpu_count()` support for VxWorks RTOS. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Add a new function :func:`os.eventfd` and related helpers to wrap the | |
|
|
||||||
| ``eventfd2`` syscall on Linux. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Add :func:`os.splice()` that allows to move data between two file | |
|
|
||||||
| descriptors without copying between kernel address space and user | |
|
|
||||||
| address space, where one of the file descriptors must refer to a | |
|
|
||||||
| pipe. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Add :data:`~os.O_EVTONLY`, :data:`~os.O_FSYNC`, :data:`~os.O_SYMLINK` | |
|
|
||||||
| and :data:`~os.O_NOFOLLOW_ANY` for macOS. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `platform <https://docs.python.org/3/whatsnew/3.10.html#platform>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Add :func:`platform.freedesktop_os_release()` to retrieve operation system | |
|
|
||||||
| identification from `freedesktop.org os-release | |
|
|
||||||
| <https://www.freedesktop.org/software/systemd/man/os-release.html>`_ standard file. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `socket <https://docs.python.org/3/whatsnew/3.10.html#socket>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The exception :exc:`socket.timeout` is now an alias of :exc:`TimeoutError`. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Add option to create MPTCP sockets with ``IPPROTO_MPTCP``. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Add ``IP_RECVTOS`` option to receive the type of service (ToS) or DSCP/ECN fields. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `ssl <https://docs.python.org/3/whatsnew/3.10.html#ssl>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The ssl module requires OpenSSL 1.1.1 or newer. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The ssl module has preliminary support for OpenSSL 3.0.0 and new option | |
|
|
||||||
| :data:`~ssl.OP_IGNORE_UNEXPECTED_EOF`. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Deprecated function and use of deprecated constants now result in | |
|
|
||||||
| a :exc:`DeprecationWarning`. :attr:`ssl.SSLContext.options` has | |
|
|
||||||
| :data:`~ssl.OP_NO_SSLv2` and :data:`~ssl.OP_NO_SSLv3` set by default and | |
|
|
||||||
| therefore cannot warn about setting the flag again. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The ssl module now has more secure default settings. Ciphers without forward | |
|
|
||||||
| secrecy or SHA-1 MAC are disabled by default. Security level 2 prohibits | |
|
|
||||||
| weak RSA, DH, and ECC keys with less than 112 bits of security. | |
|
|
||||||
| :class:`~ssl.SSLContext` defaults to minimum protocol version TLS 1.2. | |
|
|
||||||
| Settings are based on Hynek Schlawack's research. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The deprecated protocols SSL 3.0, TLS 1.0, and TLS 1.1 are no longer | |
|
|
||||||
| officially supported. Python does not block them actively. However | |
|
|
||||||
| OpenSSL build options, distro configurations, vendor patches, and cipher | |
|
|
||||||
| suites may prevent a successful handshake. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Add a *timeout* parameter to the :func:`ssl.get_server_certificate` function. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The ssl module uses heap-types and multi-phase initialization. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| A new verify flag :data:`~ssl.VERIFY_X509_PARTIAL_CHAIN` has been added. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `sys <https://docs.python.org/3/whatsnew/3.10.html#sys>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Add :data:`sys.orig_argv` attribute: the list of the original command line | |
|
|
||||||
| arguments passed to the Python executable. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Add :data:`sys.stdlib_module_names`, containing the list of the standard library | |
|
|
||||||
| module names. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `_thread <https://docs.python.org/3/whatsnew/3.10.html#_thread>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| :func:`_thread.interrupt_main` now takes an optional signal number to | |
|
|
||||||
| simulate (the default is still :data:`signal.SIGINT`). | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
|
|
||||||
.. rubric:: Notes
|
|
||||||
|
|
||||||
.. [#spm] The structural pattern matching feature is discussed in `issue #7847 <https://github.com/micropython/micropython/issues/7847>`_.
|
|
||||||
|
|
||||||
@ -1,193 +0,0 @@
|
|||||||
.. _python_35:
|
|
||||||
|
|
||||||
Python 3.5
|
|
||||||
==========
|
|
||||||
|
|
||||||
Below is a list of finalised/accepted PEPs for Python 3.5 grouped into their impact to MicroPython.
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 30 50 20
|
|
||||||
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+--------------------+
|
|
||||||
| **Extensions to the syntax** | **Status** |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| `PEP 448 <https://www.python.org/dev/peps/pep-0448/>`_ | Additional unpacking generalizations | Partial |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| `PEP 465 <https://www.python.org/dev/peps/pep-0465/>`_ | A new matrix multiplication operator | Complete |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| `PEP 492 <https://www.python.org/dev/peps/pep-0492/>`_ | Coroutines with ``async`` and ``await`` syntax | Complete |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| **Extensions and changes to runtime** |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| `PEP 461 <https://www.python.org/dev/peps/pep-0461/>`_ | % formatting for binary strings | Complete |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| `PEP 475 <https://www.python.org/dev/peps/pep-0475/>`_ | Retrying system calls that fail with ``EINTR`` | Complete |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| `PEP 479 <https://www.python.org/dev/peps/pep-0479/>`_ | Change ``StopIteration`` handling inside generators | Complete |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| **Standard library changes** |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| `PEP 471 <https://www.python.org/dev/peps/pep-0471/>`_ | ``os.scandir()`` | |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| `PEP 485 <https://www.python.org/dev/peps/pep-0485/>`_ | ``math.isclose()``, a function for testing | Complete |
|
|
||||||
| | approximate equality | |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| **Miscellaneous changes** |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| `PEP 441 <https://www.python.org/dev/peps/pep-0441/>`_ | Improved Python zip application support | |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| `PEP 486 <https://www.python.org/dev/peps/pep-0486/>`_ | Make the Python Launcher aware of virtual | Not relevant |
|
|
||||||
| | environments | |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| `PEP 484 <https://www.python.org/dev/peps/pep-0484/>`_ | Type hints (advisory only) | Complete [#fth]_ |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| `PEP 488 <https://www.python.org/dev/peps/pep-0488/>`_ | Elimination of PYO files | Not relevant |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
| `PEP 489 <https://www.python.org/dev/peps/pep-0489/>`_ | Redesigning extension module loading | |
|
|
||||||
+--------------------------------------------------------+-----------------------------------------------------+--------------------+
|
|
||||||
|
|
||||||
Other Language Changes:
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 90 10
|
|
||||||
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Added the *namereplace* error handlers. The *backslashreplace* error handlers now work with decoding and | |
|
|
||||||
| translating. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Property docstrings are now writable. This is especially useful for collections.namedtuple() docstrings | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Circular imports involving relative imports are now supported. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
|
|
||||||
|
|
||||||
New Modules:
|
|
||||||
|
|
||||||
* `typing <https://docs.python.org/3/whatsnew/3.5.html#typing>`_
|
|
||||||
|
|
||||||
* `zipzap <https://docs.python.org/3/whatsnew/3.5.html#zipapp>`_
|
|
||||||
|
|
||||||
|
|
||||||
Changes to built-in modules:
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 90 10
|
|
||||||
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `collections <https://docs.python.org/3/whatsnew/3.5.html#collections>`_ |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The *OrderedDict* class is now implemented in C, which makes it 4 to 100 times faster. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| *OrderedDict.items()* , *OrderedDict.keys()* , *OrderedDict.values()* views now support reversed() | |
|
|
||||||
| iteration. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The deque class now defines *index()*, *insert()*, and *copy()*, and supports the + and * operators. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Docstrings produced by namedtuple() can now be updated. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The UserString class now implements the *__getnewargs__()*, *__rmod__()*, *casefold()*, *format_map()*, | |
|
|
||||||
| *isprintable()*, and *maketrans()* methods to match the corresponding methods of str. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `heapq <https://docs.python.org/3/whatsnew/3.5.html#heapq>`_ |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Element comparison in *merge()* can now be customized by passing a key function in a new optional key | |
|
|
||||||
| keyword argument, and a new optional *reverse* keyword argument can be used to reverse element comparison | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `io <https://docs.python.org/3/whatsnew/3.5.html#io>`_ |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| A new *BufferedIOBase.readinto1()* method, that uses at most one call to the underlying raw stream's | |
|
|
||||||
| *RawIOBase.read()* or *RawIOBase.readinto()* methods | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `json <https://docs.python.org/3/whatsnew/3.5.html#json>`_ | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| JSON decoder now raises JSONDecodeError instead of ValueError to provide better context information about | |
|
|
||||||
| the error. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `math <https://docs.python.org/3/whatsnew/3.5.html#math>`_ |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Two new constants have been added to the math module: *inf* and *nan*. | Complete |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| A new function *isclose()* provides a way to test for approximate equality. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| A new *gcd()* function has been added. The *fractions.gcd()* function is now deprecated. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `os <https://docs.python.org/3/whatsnew/3.5.html#os>`_ |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The new *scandir()* function returning an iterator of DirEntry objects has been added. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The *urandom()* function now uses the *getrandom()* syscall on Linux 3.17 or newer, and *getentropy()* on | |
|
|
||||||
| OpenBSD 5.6 and newer, removing the need to use /dev/urandom and avoiding failures due to potential file | |
|
|
||||||
| descriptor exhaustion. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| New *get_blocking()* and *set_blocking()* functions allow getting and setting a file descriptor's blocking| |
|
|
||||||
| mode (O_NONBLOCK.) | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| There is a new *os.path.commonpath()* function returning the longest common sub-path of each passed | |
|
|
||||||
| pathname | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `re <https://docs.python.org/3/whatsnew/3.5.html#re>`_ | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| References and conditional references to groups with fixed length are now allowed in lookbehind assertions| |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The number of capturing groups in regular expressions is no longer limited to 100. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The *sub()* and *subn()* functions now replace unmatched groups with empty strings instead of raising an | |
|
|
||||||
| exception. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The *re.error* exceptions have new attributes, msg, pattern, pos, lineno, and colno, that provide better | |
|
|
||||||
| context information about the error | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `socket <https://docs.python.org/3/whatsnew/3.5.html#socket>`_ |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Functions with timeouts now use a monotonic clock, instead of a system clock. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| A new *socket.sendfile()* method allows sending a file over a socket by using the high-performance | |
|
|
||||||
| *os.sendfile()* function on UNIX, resulting in uploads being from 2 to 3 times faster than when using | |
|
|
||||||
| plain *socket.send()* | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The *socket.sendall()* method no longer resets the socket timeout every time bytes are received or sent. | |
|
|
||||||
| The socket timeout is now the maximum total duration to send all data. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The backlog argument of the *socket.listen()* method is now optional. By default it is set to SOMAXCONN or| Complete |
|
|
||||||
| to 128, whichever is less. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `ssl <https://docs.python.org/3/whatsnew/3.5.html#ssl>`_ |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Memory BIO Support | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Application-Layer Protocol Negotiation Support | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| There is a new *SSLSocket.version()* method to query the actual protocol version in use. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The SSLSocket class now implements a *SSLSocket.sendfile()* method. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The *SSLSocket.send()* method now raises either the *ssl.SSLWantReadError* or *ssl.SSLWantWriteError* | |
|
|
||||||
| exception on a non-blocking socket if the operation would block. Previously, it would return 0. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The *cert_time_to_seconds()* function now interprets the input time as UTC and not as local time, per RFC | |
|
|
||||||
| 5280. Additionally, the return value is always an int. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| New *SSLObject.shared_ciphers()* and *SSLSocket.shared_ciphers()* methods return the list of ciphers sent | |
|
|
||||||
| by the client during the handshake. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The *SSLSocket.do_handshake()*, *SSLSocket.read()*, *SSLSocket.shutdown()*, and *SSLSocket.write()* | |
|
|
||||||
| methods of the SSLSocket class no longer reset the socket timeout every time bytes are received or sent. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The *match_hostname()* function now supports matching of IP addresses. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `sys <https://docs.python.org/3/whatsnew/3.5.html#sys>`_ |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| A new *set_coroutine_wrapper()* function allows setting a global hook that will be called whenever a | |
|
|
||||||
| coroutine object is created by an async def function. A corresponding *get_coroutine_wrapper()* can be | |
|
|
||||||
| used to obtain a currently set wrapper. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| A new *is_finalizing()* function can be used to check if the Python interpreter is shutting down. | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `time <https://docs.python.org/3/whatsnew/3.5.html#time>`_ |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The *monotonic()* function is now always available | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
|
|
||||||
.. rubric:: Notes
|
|
||||||
|
|
||||||
.. [#fth] The MicroPython parser correct ignores all type hints. However, the ``typing`` module is not built-in.
|
|
||||||
@ -1,200 +0,0 @@
|
|||||||
.. _python_36:
|
|
||||||
|
|
||||||
Python 3.6
|
|
||||||
==========
|
|
||||||
|
|
||||||
Python 3.6 beta 1 was released on 12 Sep 2016, and a summary of the new features can be found here:
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 30 50 20
|
|
||||||
|
|
||||||
+-----------------------------------------------------------------------------------------------------------+-----------------+
|
|
||||||
| **New Syntax Features** | **Status** |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| `PEP 498 <https://www.python.org/dev/peps/pep-0498/>`_ | Literal String Formatting | Complete |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| `PEP 515 <https://www.python.org/dev/peps/pep-0515/>`_ | Underscores in Numeric Literals | Complete |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| `PEP 525 <https://www.python.org/dev/peps/pep-0525/>`_ | Asynchronous Generators | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| `PEP 526 <https://www.python.org/dev/peps/pep-0526/>`_ | Syntax for Variable Annotations (provisional) | Complete |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| `PEP 530 <https://www.python.org/dev/peps/pep-0530/>`_ | Asynchronous Comprehensions | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| **New Built-in 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 | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| `PEP 520 <https://www.python.org/dev/peps/pep-0520/>`_ | Preserving Class Attribute Definition Order | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| **Standard Library Changes** |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| `PEP 495 <https://www.python.org/dev/peps/pep-0495/>`_ | Local Time Disambiguation | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| `PEP 506 <https://www.python.org/dev/peps/pep-0506/>`_ | Adding A Secrets Module To The Standard Library | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| `PEP 519 <https://www.python.org/dev/peps/pep-0519/>`_ | Adding a file system path protocol | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| **CPython Internals** |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| `PEP 509 <https://www.python.org/dev/peps/pep-0509/>`_ | Add a private version to dict | Won't do |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| `PEP 523 <https://www.python.org/dev/peps/pep-0523/>`_ | Adding a frame evaluation API to CPython | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| **Linux/Window Changes** |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| `PEP 524 <https://www.python.org/dev/peps/pep-0524/>`_ | Make ``os.urandom()`` blocking on Linux | |
|
|
||||||
| | (during system startup) | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| `PEP 528 <https://www.python.org/dev/peps/pep-0528/>`_ | Change Windows console encoding to UTF-8 | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
| `PEP 529 <https://www.python.org/dev/peps/pep-0529/>`_ | Change Windows filesystem encoding to UTF-8 | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
|
||||||
|
|
||||||
Other Language Changes:
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 90 10
|
|
||||||
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| A *global* or *nonlocal* statement must now textually appear before the first use of the affected name in | |
|
|
||||||
| the same scope. Previously this was a SyntaxWarning. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| It is now possible to set a special method to None to indicate that the corresponding operation is not | |
|
|
||||||
| available. For example, if a class sets *__iter__()* to *None* , the class is not iterable. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Long sequences of repeated traceback lines are now abbreviated as *[Previous line repeated {count} more | |
|
|
||||||
| times]* | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Import now raises the new exception *ModuleNotFoundError* when it cannot find a module. Code that currently | |
|
|
||||||
| checks for ImportError (in try-except) will still work. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Class methods relying on zero-argument *super()* will now work correctly when called from metaclass methods | |
|
|
||||||
| during class creation. | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
|
|
||||||
Changes to built-in modules:
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 90 10
|
|
||||||
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `array <https://docs.python.org/3.6/whatsnew/3.6.html#array>`_ | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| Exhausted iterators of *array.array* will now stay exhausted even if the iterated array is extended. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `binascii <https://docs.python.org/3.6/whatsnew/3.6.html#binascii>`_ | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The b2a_base64() function now accepts an optional newline keyword argument to control whether the newline | Complete |
|
|
||||||
| character is appended to the return value | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `cmath <https://docs.python.org/3.6/whatsnew/3.6.html#cmath>`_ | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The new cmath.tau (τ) constant has been added | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| New constants: *cmath.inf* and *cmath.nan* to match *math.inf* and *math.nan* , and also *cmath.infj* and | |
|
|
||||||
| *cmath.nanj* to match the format used by complex repr | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `collections <https://docs.python.org/3.6/whatsnew/3.6.html#collections>`_ |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The new Collection abstract base class has been added to represent sized iterable container classes | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The new *Reversible* abstract base class represents iterable classes that also provide the *__reversed__()* | |
|
|
||||||
| method. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The new *AsyncGenerator* abstract base class represents asynchronous generators. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The *namedtuple()* function now accepts an optional keyword argument module, which, when specified, is used | |
|
|
||||||
| for the *__module__* attribute of the returned named tuple class. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The verbose and rename arguments for *namedtuple()* are now keyword-only. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| Recursive *collections.deque* instances can now be pickled. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `hashlib <https://docs.python.org/3.6/whatsnew/3.6.html#hashlib>`_ |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| BLAKE2 hash functions were added to the module. *blake2b()* and *blake2s()* are always available and support | |
|
|
||||||
| the full feature set of BLAKE2. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The SHA-3 hash functions *sha3_224()*, *sha3_256()*, *sha3_384()*, *sha3_512()*, and *SHAKE* hash functions | |
|
|
||||||
| *shake_128()* and *shake_256()* were added. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The password-based key derivation function *scrypt()* is now available with OpenSSL 1.1.0 and newer. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `json <https://docs.python.org/3.6/whatsnew/3.6.html#json>`_ |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| *json.load()* and *json.loads()* now support binary input. Encoded JSON should be represented using either | |
|
|
||||||
| UTF-8, UTF-16, or UTF-32. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `math <https://docs.python.org/3.6/whatsnew/3.6.html#math>`_ |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The new math.tau (τ) constant has been added | Complete |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `os <https://docs.python.org/3.6/whatsnew/3.6.html#os>`_ |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| A new *close()* method allows explicitly closing a *scandir()* iterator. The *scandir()* iterator now | |
|
|
||||||
| supports the context manager protocol. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| On Linux, *os.urandom()* now blocks until the system urandom entropy pool is initialized to increase the | |
|
|
||||||
| security. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The Linux *getrandom()* syscall (get random bytes) is now exposed as the new *os.getrandom()* function. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `re <https://docs.python.org/3.6/whatsnew/3.6.html#re>`_ |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| Added support of modifier spans in regular expressions. Examples: *'(?i:p)ython'* matches 'python' and | |
|
|
||||||
| 'Python', but not 'PYTHON'; *'(?i)g(?-i:v)r'* matches *'GvR'* and *'gvr'*, but not *'GVR'*. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| Match object groups can be accessed by *__getitem__*, which is equivalent to *group()*. So *mo['name']* is | |
|
|
||||||
| now equivalent to *mo.group('name')*. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| Match objects now support index-like objects as group indices. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `socket <https://docs.python.org/3.6/whatsnew/3.6.html#socket>`_ |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The *ioctl()* function now supports the *SIO_LOOPBACK_FAST_PATH* control code. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The *getsockopt()* constants *SO_DOMAIN* , *SO_PROTOCOL*, *SO_PEERSEC* , and *SO_PASSSEC* are now supported. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The *setsockopt()* now supports the *setsockopt(level, optname, None, optlen: int)* form. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The socket module now supports the address family *AF_ALG* to interface with Linux Kernel crypto API. | |
|
|
||||||
| *ALG_*, *SOL_ALG* and *sendmsg_afalg()* were added. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| New Linux constants *TCP_USER_TIMEOUT* and *TCP_CONGESTION* were added. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `ssl <https://docs.python.org/3.6/whatsnew/3.6.html#ssl>`_ |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| ssl supports OpenSSL 1.1.0. The minimum recommend version is 1.0.2. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| 3DES has been removed from the default cipher suites and ChaCha20 Poly1305 cipher suites have been added. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| *SSLContext* has better default configuration for options and ciphers. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| SSL session can be copied from one client-side connection to another with the new *SSLSession* class. TLS | |
|
|
||||||
| session resumption can speed up the initial handshake, reduce latency and improve performance. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The new *get_ciphers()* method can be used to get a list of enabled ciphers in order of cipher priority. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| All constants and flags have been converted to *IntEnum* and *IntFlags*. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| Server and client-side specific TLS protocols for *SSLContext* were added. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| Added *SSLContext.post_handshake_auth* to enable and *ssl.SSLSocket.verify_client_post_handshake()* to | |
|
|
||||||
| initiate TLS 1.3 post-handshake authentication. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `struct <https://docs.python.org/3.6/whatsnew/3.6.html#struct>`_ | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| now supports IEEE 754 half-precision floats via the 'e' format specifier. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `sys <https://docs.python.org/3.6/whatsnew/3.6.html#sys>`_ | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The new *getfilesystemencodeerrors()* function returns the name of the error mode used to convert between | |
|
|
||||||
| Unicode filenames and bytes filenames. | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `zlib <https://docs.python.org/3.6/whatsnew/3.6.html#zlib>`_ | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The *compress()* and *decompress()* functions now accept keyword arguments | |
|
|
||||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
@ -1,108 +0,0 @@
|
|||||||
.. _python_37:
|
|
||||||
|
|
||||||
Python 3.7
|
|
||||||
==========
|
|
||||||
|
|
||||||
New Features:
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 20 60 20
|
|
||||||
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+--------------------------------------+
|
|
||||||
| **Feature** | **Status** |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+--------------------------------------+
|
|
||||||
| `PEP 538 <https://www.python.org/dev/peps/pep-0538/>`_ | Coercing the legacy C locale to a UTF-8 based | |
|
|
||||||
| | locale | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+--------------------------------------+
|
|
||||||
| `PEP 539 <https://www.python.org/dev/peps/pep-0539/>`_ | A New C-API for Thread-Local Storage in CPython | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+--------------------------------------+
|
|
||||||
| `PEP 540 <https://www.python.org/dev/peps/pep-0540/>`_ | UTF-8 mode | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+--------------------------------------+
|
|
||||||
| `PEP 552 <https://www.python.org/dev/peps/pep-0552/>`_ | Deterministic pyc | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+--------------------------------------+
|
|
||||||
| `PEP 553 <https://www.python.org/dev/peps/pep-0553/>`_ | Built-in ``breakpoint()`` | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+--------------------------------------+
|
|
||||||
| `PEP 557 <https://www.python.org/dev/peps/pep-0557/>`_ | Data Classes | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+--------------------------------------+
|
|
||||||
| `PEP 560 <https://www.python.org/dev/peps/pep-0560/>`_ | Core support for typing module and generic types | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+--------------------------------------+
|
|
||||||
| `PEP 562 <https://www.python.org/dev/peps/pep-0562/>`_ | Module ``__getattr__`` and ``__dir__`` | Partial |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+--------------------------------------+
|
|
||||||
| `PEP 563 <https://www.python.org/dev/peps/pep-0563/>`_ | Postponed Evaluation of Annotations | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+--------------------------------------+
|
|
||||||
| `PEP 564 <https://www.python.org/dev/peps/pep-0564/>`_ | Time functions with nanosecond resolution | Partial [#ftimenanosec]_ |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+--------------------------------------+
|
|
||||||
| `PEP 565 <https://www.python.org/dev/peps/pep-0565/>`_ | Show DeprecationWarning in ``__main__`` | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+--------------------------------------+
|
|
||||||
| `PEP 567 <https://www.python.org/dev/peps/pep-0567/>`_ | Context Variables | |
|
|
||||||
+--------------------------------------------------------+--------------------------------------------------+--------------------------------------+
|
|
||||||
|
|
||||||
Other Language Changes:
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 90 10
|
|
||||||
|
|
||||||
+-----------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| ``async`` and ``await`` are now reserved keywords | Complete |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| ``dict`` objects must preserve insertion-order | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| More than 255 arguments can now be passed to a function; a function can now have more than 255 parameters | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| ``bytes.fromhex()`` and ``bytearray.fromhex()`` now ignore all ASCII whitespace, not only spaces | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| ``str``, ``bytes``, and ``bytearray`` gained support for the new ``isascii()`` method, which can be used to | |
|
|
||||||
| test if a string or bytes contain only the ASCII characters | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| ``ImportError`` now displays module name and module ``__file__`` path when ``from ... import ...`` fails | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| Circular imports involving absolute imports with binding a submodule to a name are now supported | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| ``object.__format__(x, '')`` is now equivalent to ``str(x)`` rather than ``format(str(self), '')`` | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| In order to better support dynamic creation of stack traces, ``types.TracebackType`` can now be | |
|
|
||||||
| instantiated from Python code, and the ``tb_next`` attribute on tracebacks is now writable | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| When using the ``-m`` switch, ``sys.path[0]`` is now eagerly expanded to the full starting directory path, | |
|
|
||||||
| rather than being left as the empty directory (which allows imports from the current working directory | |
|
|
||||||
| at the time when an import occurs) | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| The new ``-X importtime`` option or the ``PYTHONPROFILEIMPORTTIME`` environment variable can be used to | |
|
|
||||||
| show the timing of each module import | |
|
|
||||||
+-----------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
|
|
||||||
Changes to built-in modules:
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 90 10
|
|
||||||
|
|
||||||
+------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `asyncio <https://docs.python.org/3/whatsnew/3.7.html#asyncio>`_ | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| Too many to list | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `gc <https://docs.python.org/3/whatsnew/3.7.html#gc>`_ | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| New features include *gc.freeze()*, *gc.unfreeze()*, *gc-get_freeze_count* | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `math <https://docs.python.org/3/whatsnew/3.7.html#math>`_ | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| math.remainder() added to implement IEEE 754-style remainder | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `re <https://docs.python.org/3/whatsnew/3.7.html#re>`_ | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| A number of tidy up features including better support for splitting on empty strings and copy support for | |
|
|
||||||
| compiled expressions and match objects | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `sys <https://docs.python.org/3/whatsnew/3.7.html#sys>`_ | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| sys.breakpointhook() added. sys.get(/set)_coroutine_origin_tracking_depth() added | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| `time <https://docs.python.org/3/whatsnew/3.7.html#time>`_ | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
| Mostly updates to support nanosecond resolution in PEP564, see above | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+----------------+
|
|
||||||
|
|
||||||
.. rubric:: Notes
|
|
||||||
|
|
||||||
.. [#ftimenanosec] Only :func:`time.time_ns` is implemented.
|
|
||||||
@ -1,127 +0,0 @@
|
|||||||
.. _python_38:
|
|
||||||
|
|
||||||
Python 3.8
|
|
||||||
==========
|
|
||||||
|
|
||||||
Python 3.8.0 (final) was released on the 14 October 2019. The Features for 3.8
|
|
||||||
are defined in `PEP 569 <https://www.python.org/dev/peps/pep-0569/#id9>`_ and
|
|
||||||
a detailed description of the changes can be found in `What's New in Python
|
|
||||||
3.8. <https://docs.python.org/3/whatsnew/3.8.html>`_
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 20 60 20
|
|
||||||
|
|
||||||
+--------------------------------------------------------+---------------------------------------------------+---------------+
|
|
||||||
| **Features** | **Status** |
|
|
||||||
+--------------------------------------------------------+---------------------------------------------------+---------------+
|
|
||||||
| `PEP 570 <https://www.python.org/dev/peps/pep-0570/>`_ | Positional-only arguments | |
|
|
||||||
+--------------------------------------------------------+---------------------------------------------------+---------------+
|
|
||||||
| `PEP 572 <https://www.python.org/dev/peps/pep-0572/>`_ | Assignment Expressions | Complete |
|
|
||||||
+--------------------------------------------------------+---------------------------------------------------+---------------+
|
|
||||||
| `PEP 574 <https://www.python.org/dev/peps/pep-0574/>`_ | Pickle protocol 5 with out-of-band data | |
|
|
||||||
+--------------------------------------------------------+---------------------------------------------------+---------------+
|
|
||||||
| `PEP 578 <https://www.python.org/dev/peps/pep-0578/>`_ | Runtime audit hooks | |
|
|
||||||
+--------------------------------------------------------+---------------------------------------------------+---------------+
|
|
||||||
| `PEP 587 <https://www.python.org/dev/peps/pep-0587/>`_ | Python Initialization Configuration | |
|
|
||||||
+--------------------------------------------------------+---------------------------------------------------+---------------+
|
|
||||||
| `PEP 590 <https://www.python.org/dev/peps/pep-0590/>`_ | Vectorcall: a fast calling protocol for CPython | |
|
|
||||||
+--------------------------------------------------------+---------------------------------------------------+---------------+
|
|
||||||
| **Miscellaneous** |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| f-strings support = for self-documenting expressions and debugging | Complete |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
|
|
||||||
Other Language Changes:
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 90 10
|
|
||||||
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| A *continue* statement was illegal in the *finally* clause due to a problem with the implementation. In | Complete |
|
|
||||||
| Python 3.8 this restriction was lifted | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| The *bool*, *int* , and *fractions.Fraction* types now have an *as_integer_ratio()* method like that found | |
|
|
||||||
| in *float* and *decimal.Decimal* | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Constructors of *int*, *float* and *complex* will now use the *__index__()* special method, if available | |
|
|
||||||
| and the corresponding method *__int__()*, *__float__()* or *__complex__()* is not available | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Added support of *\N{name}* escapes in regular expressions | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Dict and dictviews are now iterable in reversed insertion order using *reversed()* | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| The syntax allowed for keyword names in function calls was further restricted. In particular, | |
|
|
||||||
| f((keyword)=arg) is no longer allowed | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Generalized iterable unpacking in yield and return statements no longer requires enclosing parentheses | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| When a comma is missed in code such as [(10, 20) (30, 40)], the compiler displays a SyntaxWarning with a | |
|
|
||||||
| helpful suggestion | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Arithmetic operations between subclasses of *datetime.date* or *datetime.datetime* and *datetime.timedelta*| |
|
|
||||||
| objects now return an instance of the subclass, rather than the base class | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| When the Python interpreter is interrupted by *Ctrl-C (SIGINT)* and the resulting *KeyboardInterrupt* | |
|
|
||||||
| exception is not caught, the Python process now exits via a SIGINT signal or with the correct exit code | |
|
|
||||||
| such that the calling process can detect that it died due to a *Ctrl-C* | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Some advanced styles of programming require updating the *types.CodeType* object for an existing function | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| For integers, the three-argument form of the pow() function now permits the exponent to be negative in the | |
|
|
||||||
| case where the base is relatively prime to the modulus | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Dict comprehensions have been synced-up with dict literals so that the key is computed first and the value | |
|
|
||||||
| second | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| The *object.__reduce__()* method can now return a tuple from two to six elements long | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
|
|
||||||
Changes to built-in modules:
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 90 10
|
|
||||||
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| `asyncio <https://docs.python.org/3/whatsnew/3.8.html#asyncio>`_ |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| *asyncio.run()* has graduated from the provisional to stable API | Complete |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Running *python -m asyncio* launches a natively async REPL | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| The exception *asyncio.CancelledError* now inherits from *BaseException* rather than *Exception* and no | Complete |
|
|
||||||
| longer inherits from *concurrent.futures.CancelledError* | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Added *asyncio.Task.get_coro()* for getting the wrapped coroutine within an *asyncio.Task* | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Asyncio tasks can now be named, either by passing the name keyword argument to *asyncio.create_task()* or | |
|
|
||||||
| the *create_task()* event loop method, or by calling the *set_name()* method on the task object | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Added support for Happy Eyeballs to *asyncio.loop.create_connection()*. To specify the behavior, two new | |
|
|
||||||
| parameters have been added: *happy_eyeballs_delay* and interleave. | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| `gc <https://docs.python.org/3/whatsnew/3.8.html#gc>`_ |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| *get_objects()* can now receive an optional generation parameter indicating a generation to get objects | |
|
|
||||||
| from. (Note, though, that while *gc* is a built-in, *get_objects()* is not implemented for MicroPython) | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| `math <https://docs.python.org/3/whatsnew/3.8.html#math>`_ |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Added new function *math.dist()* for computing Euclidean distance between two points | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Expanded the *math.hypot()* function to handle multiple dimensions | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Added new function, *math.prod()*, as analogous function to *sum()* that returns the product of a "start" | |
|
|
||||||
| value (default: 1) times an iterable of numbers | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Added two new combinatoric functions *math.perm()* and *math.comb()* | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Added a new function *math.isqrt()* for computing accurate integer square roots without conversion to | |
|
|
||||||
| floating point | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| The function *math.factorial()* no longer accepts arguments that are not int-like | Complete |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| `sys <https://docs.python.org/3/whatsnew/3.8.html#sys>`_ |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
| Add new *sys.unraisablehook()* function which can be overridden to control how "unraisable exceptions" | |
|
|
||||||
| are handled | |
|
|
||||||
+------------------------------------------------------------------------------------------------------------+-------------+
|
|
||||||
@ -1,134 +0,0 @@
|
|||||||
.. _python_39:
|
|
||||||
|
|
||||||
Python 3.9
|
|
||||||
==========
|
|
||||||
|
|
||||||
Python 3.9.0 (final) was released on the 5th October 2020. The Features for 3.9 are
|
|
||||||
defined in `PEP 596 <https://www.python.org/dev/peps/pep-0596/#features-for-3-9>`_
|
|
||||||
and a detailed description of the changes can be found in
|
|
||||||
`What's New in Python 3.9 <https://docs.python.org/3/whatsnew/3.9.html>`_
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 20 60 20
|
|
||||||
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+----------------------+
|
|
||||||
| **Features** | | **Status** |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+----------------------+
|
|
||||||
| `PEP 573 <https://www.python.org/dev/peps/pep-0573/>`_ | Fast access to module state from methods of C | Not relevant |
|
|
||||||
| | extension types | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+----------------------+
|
|
||||||
| `PEP 584 <https://www.python.org/dev/peps/pep-0584/>`_ | Union operators added to dict | Complete [#pep584]_ |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+----------------------+
|
|
||||||
| `PEP 585 <https://www.python.org/dev/peps/pep-0584/>`_ | Type hinting generics in standard collections | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+----------------------+
|
|
||||||
| `PEP 593 <https://www.python.org/dev/peps/pep-0593/>`_ | Flexible function and variable annotations | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+----------------------+
|
|
||||||
| `PEP 602 <https://www.python.org/dev/peps/pep-0602/>`_ | CPython adopts an annual release cycle. Instead of | Not relevant |
|
|
||||||
| | annual, aiming for two month release cycle | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+----------------------+
|
|
||||||
| `PEP 614 <https://www.python.org/dev/peps/pep-0614/>`_ | Relaxed grammar restrictions on decorators | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+----------------------+
|
|
||||||
| `PEP 615 <https://www.python.org/dev/peps/pep-0615/>`_ | The IANA Time Zone Database is now present in the | |
|
|
||||||
| | standard library in the zoneinfo module | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+----------------------+
|
|
||||||
| `PEP 616 <https://www.python.org/dev/peps/pep-0616/>`_ | String methods to remove prefixes and suffixes | |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+----------------------+
|
|
||||||
| `PEP 617 <https://www.python.org/dev/peps/pep-0617/>`_ | CPython now uses a new parser based on PEG | Not relevant |
|
|
||||||
+--------------------------------------------------------+----------------------------------------------------+----------------------+
|
|
||||||
|
|
||||||
Other Language Changes:
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 90 10
|
|
||||||
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| *__import__()* now raises *ImportError* instead of *ValueError* | Complete |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Python now gets the absolute path of the script filename specified on the command line (ex: *python3* | |
|
|
||||||
| *script.py*): the *__file__* attribute of the *__main__* module became an absolute path, rather than a | |
|
|
||||||
| relative path | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| By default, for best performance, the errors argument is only checked at the first encoding/decoding error | |
|
|
||||||
| and the encoding argument is sometimes ignored for empty strings | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| *"".replace("", s, n)* now returns *s* instead of an empty string for all non-zero n. It is now consistent | |
|
|
||||||
| with *"".replace("", s)* | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Any valid expression can now be used as a decorator. Previously, the grammar was much more restrictive | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Parallel running of *aclose()* / *asend()* / *athrow()* is now prohibited, and *ag_running* now reflects | |
|
|
||||||
| the actual running status of the async generator | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Unexpected errors in calling the *__iter__* method are no longer masked by TypeError in the in operator and | |
|
|
||||||
| functions contains(), indexOf() and countOf() of the operator module | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Unparenthesized lambda expressions can no longer be the expression part in an if clause in comprehensions | |
|
|
||||||
| and generator expressions | |
|
|
||||||
+-------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
|
|
||||||
Changes to built-in modules:
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
:widths: 90 10
|
|
||||||
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `asyncio <https://docs.python.org/3/whatsnew/3.9.html#asyncio>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Due to significant security concerns, the reuse_address parameter of *asyncio.loop.create_datagram_endpoint()*| |
|
|
||||||
| is no longer supported | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Added a new coroutine *shutdown_default_executor()* that schedules a shutdown for the default executor that | |
|
|
||||||
| waits on the *ThreadPoolExecutor* to finish closing. Also, *asyncio.run()* has been updated to use the new | |
|
|
||||||
| coroutine. | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Added *asyncio.PidfdChildWatcher*, a Linux-specific child watcher implementation that polls process file | |
|
|
||||||
| descriptors | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| added a new *coroutine asyncio.to_thread()* | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| When cancelling the task due to a timeout, *asyncio.wait_for()* will now wait until the cancellation is | |
|
|
||||||
| complete also in the case when timeout is <= 0, like it does with positive timeouts | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| *asyncio* now raises *TyperError* when calling incompatible methods with an *ssl.SSLSocket* socket | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `gc <https://docs.python.org/3/whatsnew/3.9.html#gc>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Garbage collection does not block on resurrected objects | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Added a new function *gc.is_finalized()* to check if an object has been finalized by the garbage collector | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `math <https://docs.python.org/3/whatsnew/3.9.html#math>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Expanded the *math.gcd()* function to handle multiple arguments. Formerly, it only supported two arguments | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Added *math.lcm()*: return the least common multiple of specified arguments | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Added *math.nextafter()*: return the next floating-point value after x towards y | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Added *math.ulp()*: return the value of the least significant bit of a float | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `os <https://docs.python.org/3/whatsnew/3.9.html#os>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Exposed the Linux-specific *os.pidfd_open()* and *os.P_PIDFD* | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The *os.unsetenv()* function is now also available on Windows | Complete |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| The *os.putenv()* and *os.unsetenv()* functions are now always available | Complete |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Added *os.waitstatus_to_exitcode()* function: convert a wait status to an exit code | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `random <https://docs.python.org/3/whatsnew/3.9.html#random>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Added a new *random.Random.randbytes* method: generate random bytes | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| `sys <https://docs.python.org/3/whatsnew/3.9.html#sys>`_ |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Added a new *sys.platlibdir* attribute: name of the platform-specific library directory | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
| Previously, *sys.stderr* was block-buffered when non-interactive. Now stderr defaults to always being | |
|
|
||||||
| line-buffered | |
|
|
||||||
+---------------------------------------------------------------------------------------------------------------+---------------+
|
|
||||||
|
|
||||||
.. rubric:: Notes
|
|
||||||
|
|
||||||
.. [#pep584] PEP 584 ``dict`` union operator is only available on MicroPython builds with ``MICROPY_CPYTHON_COMPAT`` enabled.
|
|
||||||
@ -16,10 +16,7 @@ working with this board it may be useful to get an overview of the microcontroll
|
|||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
general.rst
|
general.rst
|
||||||
tutorial/index.rst
|
tutorial/intro.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
|
Installing MicroPython
|
||||||
----------------------
|
----------------------
|
||||||
@ -60,25 +57,17 @@ The :mod:`esp32` module::
|
|||||||
|
|
||||||
import esp32
|
import esp32
|
||||||
|
|
||||||
|
esp32.hall_sensor() # read the internal hall sensor
|
||||||
esp32.raw_temperature() # read the internal temperature of the MCU, in Fahrenheit
|
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
|
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
|
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.
|
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
|
Networking
|
||||||
----------
|
----------
|
||||||
|
|
||||||
WLAN
|
|
||||||
^^^^
|
|
||||||
|
|
||||||
The :mod:`network` module::
|
The :mod:`network` module::
|
||||||
|
|
||||||
import network
|
import network
|
||||||
@ -87,12 +76,12 @@ The :mod:`network` module::
|
|||||||
wlan.active(True) # activate the interface
|
wlan.active(True) # activate the interface
|
||||||
wlan.scan() # scan for access points
|
wlan.scan() # scan for access points
|
||||||
wlan.isconnected() # check if the station is connected to an AP
|
wlan.isconnected() # check if the station is connected to an AP
|
||||||
wlan.connect('ssid', 'key') # connect to an AP
|
wlan.connect('essid', 'password') # connect to an AP
|
||||||
wlan.config('mac') # get the interface's MAC address
|
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.AP_IF) # create access-point 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(essid='ESP-AP') # set the ESSID of the access point
|
||||||
ap.config(max_clients=10) # set how many clients can connect to the network
|
ap.config(max_clients=10) # set how many clients can connect to the network
|
||||||
ap.active(True) # activate the interface
|
ap.active(True) # activate the interface
|
||||||
|
|
||||||
@ -104,13 +93,13 @@ A useful function for connecting to your local WiFi network is::
|
|||||||
wlan.active(True)
|
wlan.active(True)
|
||||||
if not wlan.isconnected():
|
if not wlan.isconnected():
|
||||||
print('connecting to network...')
|
print('connecting to network...')
|
||||||
wlan.connect('ssid', 'key')
|
wlan.connect('essid', 'password')
|
||||||
while not wlan.isconnected():
|
while not wlan.isconnected():
|
||||||
pass
|
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
|
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
|
to create and use TCP/UDP sockets as usual, and the ``urequests`` module for
|
||||||
convenient HTTP requests.
|
convenient HTTP requests.
|
||||||
|
|
||||||
After a call to ``wlan.connect()``, the device will by default retry to connect
|
After a call to ``wlan.connect()``, the device will by default retry to connect
|
||||||
@ -121,56 +110,6 @@ 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
|
attempts (0 means it won't retry, -1 will restore the default behaviour of trying
|
||||||
to reconnect forever).
|
to reconnect forever).
|
||||||
|
|
||||||
LAN
|
|
||||||
^^^
|
|
||||||
|
|
||||||
To use the wired interfaces one has to specify the pins and mode ::
|
|
||||||
|
|
||||||
import network
|
|
||||||
|
|
||||||
lan = network.LAN(mdc=PIN_MDC, ...) # Set the pin and mode configuration
|
|
||||||
lan.active(True) # activate the interface
|
|
||||||
lan.ipconfig('addr4') # get the interface's IPv4 addresses
|
|
||||||
|
|
||||||
|
|
||||||
The keyword arguments for the constructor defining the PHY type and interface are:
|
|
||||||
|
|
||||||
- mdc=pin-object # set the mdc and mdio pins.
|
|
||||||
- mdio=pin-object
|
|
||||||
- reset=pin-object # set the reset pin of the PHY device.
|
|
||||||
- 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.
|
|
||||||
|
|
||||||
These are working configurations for LAN interfaces of popular boards::
|
|
||||||
|
|
||||||
# Olimex ESP32-GATEWAY: power controlled by Pin(5)
|
|
||||||
# Olimex ESP32 PoE and ESP32-PoE ISO: power controlled by Pin(12)
|
|
||||||
|
|
||||||
lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), power=machine.Pin(5),
|
|
||||||
phy_type=network.PHY_LAN8720, phy_addr=0,
|
|
||||||
ref_clk=machine.Pin(17), ref_clk_mode=machine.Pin.OUT)
|
|
||||||
|
|
||||||
# Wireless-Tag's WT32-ETH01
|
|
||||||
|
|
||||||
lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18),
|
|
||||||
phy_type=network.PHY_LAN8720, phy_addr=1, power=None)
|
|
||||||
|
|
||||||
# Wireless-Tag's WT32-ETH01 v1.4
|
|
||||||
|
|
||||||
lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18),
|
|
||||||
phy_type=network.PHY_LAN8720, phy_addr=1,
|
|
||||||
power=machine.Pin(16))
|
|
||||||
|
|
||||||
# Espressif ESP32-Ethernet-Kit_A_V1.2
|
|
||||||
|
|
||||||
lan = network.LAN(id=0, mdc=Pin(23), mdio=Pin(18), power=Pin(5),
|
|
||||||
phy_type=network.PHY_IP101, phy_addr=1)
|
|
||||||
|
|
||||||
Delay and timing
|
Delay and timing
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
@ -221,7 +160,6 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
|
|||||||
|
|
||||||
p4 = Pin(4, Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
|
p4 = Pin(4, Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
|
||||||
p5 = Pin(5, Pin.OUT, value=1) # set pin high on creation
|
p5 = Pin(5, Pin.OUT, value=1) # set pin high on creation
|
||||||
p6 = Pin(6, Pin.OUT, drive=Pin.DRIVE_3) # set maximum drive strength
|
|
||||||
|
|
||||||
Available Pins are from the following ranges (inclusive): 0-19, 21-23, 25-27, 32-39.
|
Available Pins are from the following ranges (inclusive): 0-19, 21-23, 25-27, 32-39.
|
||||||
These correspond to the actual GPIO pin numbers of ESP32 chip. Note that many
|
These correspond to the actual GPIO pin numbers of ESP32 chip. Note that many
|
||||||
@ -229,23 +167,6 @@ end-user boards use their own adhoc pin numbering (marked e.g. D0, D1, ...).
|
|||||||
For mapping between board logical pins and physical chip pins consult your board
|
For mapping between board logical pins and physical chip pins consult your board
|
||||||
documentation.
|
documentation.
|
||||||
|
|
||||||
Four drive strengths are supported, using the ``drive`` keyword argument to the
|
|
||||||
``Pin()`` constructor or ``Pin.init()`` method, with different corresponding
|
|
||||||
safe maximum source/sink currents and approximate internal driver resistances:
|
|
||||||
|
|
||||||
- ``Pin.DRIVE_0``: 5mA / 130 ohm
|
|
||||||
- ``Pin.DRIVE_1``: 10mA / 60 ohm
|
|
||||||
- ``Pin.DRIVE_2``: 20mA / 30 ohm (default strength if not configured)
|
|
||||||
- ``Pin.DRIVE_3``: 40mA / 15 ohm
|
|
||||||
|
|
||||||
The ``hold=`` keyword argument to ``Pin()`` and ``Pin.init()`` will enable the
|
|
||||||
ESP32 "pad hold" feature. When set to ``True``, the pin configuration
|
|
||||||
(direction, pull resistors and output value) will be held and any further
|
|
||||||
changes (including changing the output level) will not be applied. Setting
|
|
||||||
``hold=False`` will immediately apply any outstanding pin configuration changes
|
|
||||||
and release the pin. Using ``hold=True`` while a pin is already held will apply
|
|
||||||
any configuration changes and then immediately reapply the hold.
|
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
* Pins 1 and 3 are REPL UART TX and RX respectively
|
* Pins 1 and 3 are REPL UART TX and RX respectively
|
||||||
@ -255,7 +176,8 @@ Notes:
|
|||||||
|
|
||||||
* Pins 34-39 are input only, and also do not have internal pull-up resistors
|
* Pins 34-39 are input only, and also do not have internal pull-up resistors
|
||||||
|
|
||||||
* See :ref:`Deep_sleep_Mode` for a discussion of pin behaviour during sleep
|
* The pull value of some pins can be set to ``Pin.PULL_HOLD`` to reduce power
|
||||||
|
consumption during deepsleep.
|
||||||
|
|
||||||
There's a higher-level abstraction :ref:`machine.Signal <machine.Signal>`
|
There's a higher-level abstraction :ref:`machine.Signal <machine.Signal>`
|
||||||
which can be used to invert a pin. Useful for illuminating active-low LEDs
|
which can be used to invert a pin. Useful for illuminating active-low LEDs
|
||||||
@ -277,10 +199,9 @@ They each have default GPIO assigned to them, however depending on your
|
|||||||
ESP32 variant and board, these pins may conflict with embedded flash,
|
ESP32 variant and board, these pins may conflict with embedded flash,
|
||||||
onboard PSRAM or peripherals.
|
onboard PSRAM or peripherals.
|
||||||
|
|
||||||
Any GPIO can be used for hardware UARTs using the GPIO matrix, except for
|
Any GPIO can be used for hardware UARTs using the GPIO matrix, so to avoid
|
||||||
input-only pins 34-39 that can be used as ``rx``. To avoid conflicts simply
|
conflicts simply provide ``tx`` and ``rx`` pins when constructing. The default
|
||||||
provide ``tx`` and ``rx`` pins when constructing. The default pins listed
|
pins listed below.
|
||||||
below.
|
|
||||||
|
|
||||||
===== ===== ===== =====
|
===== ===== ===== =====
|
||||||
\ UART0 UART1 UART2
|
\ UART0 UART1 UART2
|
||||||
@ -297,158 +218,72 @@ range from 1Hz to 40MHz but there is a tradeoff; as the base frequency
|
|||||||
*increases* the duty resolution *decreases*. See
|
*increases* the duty resolution *decreases*. See
|
||||||
`LED Control <https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/ledc.html>`_
|
`LED Control <https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/ledc.html>`_
|
||||||
for more details.
|
for more details.
|
||||||
|
Currently the duty cycle has to be in the range of 0-1023.
|
||||||
|
|
||||||
Use the :ref:`machine.PWM <machine.PWM>` class::
|
Use the ``machine.PWM`` class::
|
||||||
|
|
||||||
from machine import Pin, PWM
|
from machine import Pin, PWM
|
||||||
|
|
||||||
pwm0 = PWM(Pin(0), freq=5000, duty_u16=32768) # create PWM object from a pin
|
pwm0 = PWM(Pin(0)) # create PWM object from a pin
|
||||||
freq = pwm0.freq() # get current frequency
|
pwm0.freq() # get current frequency
|
||||||
pwm0.freq(1000) # set PWM frequency from 1Hz to 40MHz
|
pwm0.freq(1000) # set frequency
|
||||||
|
pwm0.duty() # get current duty cycle
|
||||||
duty = pwm0.duty() # get current duty cycle, range 0-1023 (default 512, 50%)
|
pwm0.duty(200) # set duty cycle
|
||||||
pwm0.duty(256) # set duty cycle from 0 to 1023 as a ratio duty/1023, (now 25%)
|
|
||||||
|
|
||||||
duty_u16 = pwm0.duty_u16() # get current duty cycle, range 0-65535
|
|
||||||
pwm0.duty_u16(2**16*3//4) # set duty cycle from 0 to 65535 as a ratio duty_u16/65535, (now 75%)
|
|
||||||
|
|
||||||
duty_ns = pwm0.duty_ns() # get current pulse width in ns
|
|
||||||
pwm0.duty_ns(250_000) # set pulse width in nanoseconds from 0 to 1_000_000_000/freq, (now 25%)
|
|
||||||
|
|
||||||
pwm0.deinit() # turn off PWM on the pin
|
pwm0.deinit() # turn off PWM on the pin
|
||||||
|
|
||||||
pwm2 = PWM(Pin(2), freq=20000, duty=512) # create and configure in one go
|
pwm2 = PWM(Pin(2), freq=20000, duty=512) # create and configure in one go
|
||||||
print(pwm2) # view PWM settings
|
|
||||||
|
|
||||||
ESP chips have different hardware peripherals:
|
|
||||||
|
|
||||||
===================================================== ======== ======== ========
|
|
||||||
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
|
|
||||||
have the same frequency. On the other hand, 16 independent PWM duty cycles are
|
|
||||||
possible at the same frequency.
|
|
||||||
|
|
||||||
See more examples in the :ref:`esp32_pwm` tutorial.
|
|
||||||
|
|
||||||
DAC (digital to analog conversion)
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
On the ESP32, DAC functionality is available on pins 25, 26.
|
|
||||||
On the ESP32S2, DAC functionality is available on pins 17, 18.
|
|
||||||
|
|
||||||
Use the DAC::
|
|
||||||
|
|
||||||
from machine import DAC, Pin
|
|
||||||
|
|
||||||
dac = DAC(Pin(25)) # create an DAC object acting on a pin
|
|
||||||
dac.write(128) # set a raw analog value in the range 0-255, 50% now
|
|
||||||
|
|
||||||
ADC (analog to digital conversion)
|
ADC (analog to digital conversion)
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
On the ESP32, ADC functionality is available on pins 32-39 (ADC block 1) and
|
On the ESP32 ADC functionality is available on Pins 32-39. Note that, when
|
||||||
pins 0, 2, 4, 12-15 and 25-27 (ADC block 2).
|
using the default configuration, input voltages on the ADC pin must be between
|
||||||
|
0.0v and 1.0v (anything above 1.0v will just read as 4095). Attenuation must
|
||||||
|
be applied in order to increase this usable voltage range.
|
||||||
|
|
||||||
Use the :ref:`machine.ADC <machine.ADC>` class::
|
Use the :ref:`machine.ADC <machine.ADC>` class::
|
||||||
|
|
||||||
from machine import ADC
|
from machine import ADC
|
||||||
|
|
||||||
adc = ADC(pin) # create an ADC object acting on a pin
|
adc = ADC(Pin(32)) # create ADC object on ADC pin
|
||||||
val = adc.read_u16() # read a raw analog value in the range 0-65535
|
adc.read() # read value, 0-4095 across voltage range 0.0v - 1.0v
|
||||||
val = adc.read_uv() # read an analog value in microvolts
|
|
||||||
|
|
||||||
ADC block 2 is also used by WiFi and so attempting to read analog values from
|
adc.atten(ADC.ATTN_11DB) # set 11dB input attenuation (voltage range roughly 0.0v - 3.6v)
|
||||||
block 2 pins when WiFi is active will raise an exception.
|
adc.width(ADC.WIDTH_9BIT) # set 9 bit return values (returned range 0-511)
|
||||||
|
adc.read() # read value using the newly configured attenuation and width
|
||||||
|
|
||||||
The internal ADC reference voltage is typically 1.1V, but varies slightly from
|
ESP32 specific ADC class method reference:
|
||||||
package to package. The ADC is less linear close to the reference voltage
|
|
||||||
(particularly at higher attenuations) and has a minimum measurement voltage
|
|
||||||
around 100mV, voltages at or below this will read as 0. To read voltages
|
|
||||||
accurately, it is recommended to use the ``read_uv()`` method (see below).
|
|
||||||
|
|
||||||
ESP32-specific ADC class method reference:
|
.. method:: ADC.atten(attenuation)
|
||||||
|
|
||||||
.. class:: ADC(pin, *, atten)
|
This method allows for the setting of the amount of attenuation on the
|
||||||
|
input of the ADC. This allows for a wider possible input voltage range,
|
||||||
|
at the cost of accuracy (the same number of bits now represents a wider
|
||||||
|
range). The possible attenuation options are:
|
||||||
|
|
||||||
Return the ADC object for the specified pin. ESP32 does not support
|
- ``ADC.ATTN_0DB``: 0dB attenuation, gives a maximum input voltage
|
||||||
different timings for ADC sampling and so the ``sample_ns`` keyword argument
|
of 1.00v - this is the default configuration
|
||||||
is not supported.
|
- ``ADC.ATTN_2_5DB``: 2.5dB attenuation, gives a maximum input voltage
|
||||||
|
of approximately 1.34v
|
||||||
To read voltages above the reference voltage, apply input attenuation with
|
- ``ADC.ATTN_6DB``: 6dB attenuation, gives a maximum input voltage
|
||||||
the ``atten`` keyword argument. Valid values (and approximate linear
|
of approximately 2.00v
|
||||||
measurement ranges) are:
|
- ``ADC.ATTN_11DB``: 11dB attenuation, gives a maximum input voltage
|
||||||
|
of approximately 3.6v
|
||||||
- ``ADC.ATTN_0DB``: No attenuation (100mV - 950mV)
|
|
||||||
- ``ADC.ATTN_2_5DB``: 2.5dB attenuation (100mV - 1250mV)
|
|
||||||
- ``ADC.ATTN_6DB``: 6dB attenuation (150mV - 1750mV)
|
|
||||||
- ``ADC.ATTN_11DB``: 11dB attenuation (150mV - 2450mV)
|
|
||||||
|
|
||||||
.. Warning::
|
.. Warning::
|
||||||
Note that the absolute maximum voltage rating for input pins is 3.6V. Going
|
Despite 11dB attenuation allowing for up to a 3.6v range, note that the
|
||||||
near to this boundary risks damage to the IC!
|
absolute maximum voltage rating for the input pins is 3.6v, and so going
|
||||||
|
near this boundary may be damaging to the IC!
|
||||||
|
|
||||||
.. method:: ADC.read_uv()
|
.. method:: ADC.width(width)
|
||||||
|
|
||||||
This method uses the known characteristics of the ADC and per-package eFuse
|
This method allows for the setting of the number of bits to be utilised
|
||||||
values - set during manufacture - to return a calibrated input voltage
|
and returned during ADC reads. Possible width options are:
|
||||||
(before attenuation) in microvolts. The returned value has only millivolt
|
|
||||||
resolution (i.e., will always be a multiple of 1000 microvolts).
|
|
||||||
|
|
||||||
The calibration is only valid across the linear range of the ADC. In
|
|
||||||
particular, an input tied to ground will read as a value above 0 microvolts.
|
|
||||||
Within the linear range, however, more accurate and consistent results will
|
|
||||||
be obtained than using `read_u16()` and scaling the result with a constant.
|
|
||||||
|
|
||||||
The ESP32 port also supports the :ref:`machine.ADC <machine.ADCBlock>` API:
|
|
||||||
|
|
||||||
.. class:: ADCBlock(id, *, bits)
|
|
||||||
|
|
||||||
Return the ADC block object with the given ``id`` (1 or 2) and initialize
|
|
||||||
it to the specified resolution (9 to 12-bits depending on the ESP32 series)
|
|
||||||
or the highest supported resolution if not specified.
|
|
||||||
|
|
||||||
.. method:: ADCBlock.connect(pin)
|
|
||||||
ADCBlock.connect(channel)
|
|
||||||
ADCBlock.connect(channel, pin)
|
|
||||||
|
|
||||||
Return the ``ADC`` object for the specified ADC pin or channel number.
|
|
||||||
Arbitrary connection of ADC channels to GPIO is not supported and so
|
|
||||||
specifying a pin that is not connected to this block, or specifying a
|
|
||||||
mismatched channel and pin, will raise an exception.
|
|
||||||
|
|
||||||
Legacy methods:
|
|
||||||
|
|
||||||
.. method:: ADC.read()
|
|
||||||
|
|
||||||
This method returns the raw ADC value ranged according to the resolution of
|
|
||||||
the block, e.g., 0-4095 for 12-bit resolution.
|
|
||||||
|
|
||||||
.. method:: ADC.atten(atten)
|
|
||||||
|
|
||||||
Equivalent to ``ADC.init(atten=atten)``.
|
|
||||||
|
|
||||||
.. method:: ADC.width(bits)
|
|
||||||
|
|
||||||
Equivalent to ``ADC.block().init(bits=bits)``.
|
|
||||||
|
|
||||||
For compatibility, the ``ADC`` object also provides constants matching the
|
|
||||||
supported ADC resolutions:
|
|
||||||
|
|
||||||
- ``ADC.WIDTH_9BIT`` = 9
|
|
||||||
- ``ADC.WIDTH_10BIT`` = 10
|
|
||||||
- ``ADC.WIDTH_11BIT`` = 11
|
|
||||||
- ``ADC.WIDTH_12BIT`` = 12
|
|
||||||
|
|
||||||
|
- ``ADC.WIDTH_9BIT``: 9 bit data
|
||||||
|
- ``ADC.WIDTH_10BIT``: 10 bit data
|
||||||
|
- ``ADC.WIDTH_11BIT``: 11 bit data
|
||||||
|
- ``ADC.WIDTH_12BIT``: 12 bit data - this is the default configuration
|
||||||
|
|
||||||
Software SPI bus
|
Software SPI bus
|
||||||
----------------
|
----------------
|
||||||
@ -590,8 +425,6 @@ See :ref:`machine.WDT <machine.WDT>`. ::
|
|||||||
wdt = WDT(timeout=5000)
|
wdt = WDT(timeout=5000)
|
||||||
wdt.feed()
|
wdt.feed()
|
||||||
|
|
||||||
.. _Deep_sleep_mode:
|
|
||||||
|
|
||||||
Deep-sleep mode
|
Deep-sleep mode
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
@ -611,64 +444,30 @@ Notes:
|
|||||||
* Calling ``deepsleep()`` without an argument will put the device to sleep
|
* Calling ``deepsleep()`` without an argument will put the device to sleep
|
||||||
indefinitely
|
indefinitely
|
||||||
* A software reset does not change the reset cause
|
* A software reset does not change the reset cause
|
||||||
|
* There may be some leakage current flowing through enabled internal pullups.
|
||||||
|
To further reduce power consumption it is possible to disable the internal pullups::
|
||||||
|
|
||||||
Some ESP32 pins (0, 2, 4, 12-15, 25-27, 32-39) are connected to the RTC during
|
p1 = Pin(4, Pin.IN, Pin.PULL_HOLD)
|
||||||
deep-sleep and can be used to wake the device with the ``wake_on_`` functions in
|
|
||||||
the :mod:`esp32` module. The output-capable RTC pins (all except 34-39) will
|
|
||||||
also retain their pull-up or pull-down resistor configuration when entering
|
|
||||||
deep-sleep.
|
|
||||||
|
|
||||||
If the pull resistors are not actively required during deep-sleep and are likely
|
After leaving deepsleep it may be necessary to un-hold the pin explicitly (e.g. if
|
||||||
to cause current leakage (for example a pull-up resistor is connected to ground
|
it is an output pin) via::
|
||||||
through a switch), then they should be disabled to save power before entering
|
|
||||||
deep-sleep mode::
|
|
||||||
|
|
||||||
from machine import Pin, deepsleep
|
p1 = Pin(4, Pin.OUT, None)
|
||||||
|
|
||||||
# configure input RTC pin with pull-up on boot
|
|
||||||
pin = Pin(2, Pin.IN, Pin.PULL_UP)
|
|
||||||
|
|
||||||
# disable pull-up and put the device to sleep for 10 seconds
|
|
||||||
pin.init(pull=None)
|
|
||||||
machine.deepsleep(10000)
|
|
||||||
|
|
||||||
Output-configured RTC pins will also retain their output direction and level in
|
|
||||||
deep-sleep if pad hold is enabled with the ``hold=True`` argument to
|
|
||||||
``Pin.init()``.
|
|
||||||
|
|
||||||
Non-RTC GPIO pins will be disconnected by default on entering deep-sleep.
|
|
||||||
Configuration of non-RTC pins - including output level - can be retained by
|
|
||||||
enabling pad hold on the pin and enabling GPIO pad hold during deep-sleep::
|
|
||||||
|
|
||||||
from machine import Pin, deepsleep
|
|
||||||
import esp32
|
|
||||||
|
|
||||||
opin = Pin(19, Pin.OUT, value=1, hold=True) # hold output level
|
|
||||||
ipin = Pin(21, Pin.IN, Pin.PULL_UP, hold=True) # hold pull-up
|
|
||||||
|
|
||||||
# enable pad hold in deep-sleep for non-RTC GPIO
|
|
||||||
esp32.gpio_deep_sleep_hold(True)
|
|
||||||
|
|
||||||
# put the device to sleep for 10 seconds
|
|
||||||
deepsleep(10000)
|
|
||||||
|
|
||||||
The pin configuration - including the pad hold - will be retained on wake from
|
|
||||||
sleep. See :ref:`Pins_and_GPIO` above for a further discussion of pad holding.
|
|
||||||
|
|
||||||
SD card
|
SD card
|
||||||
-------
|
-------
|
||||||
|
|
||||||
See :ref:`machine.SDCard <machine.SDCard>`. ::
|
See :ref:`machine.SDCard <machine.SDCard>`. ::
|
||||||
|
|
||||||
import machine, os, vfs
|
import machine, os
|
||||||
|
|
||||||
# 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)
|
sd = machine.SDCard(slot=2)
|
||||||
vfs.mount(sd, '/sd') # mount
|
os.mount(sd, "/sd") # mount
|
||||||
|
|
||||||
os.listdir('/sd') # list directory contents
|
os.listdir('/sd') # list directory contents
|
||||||
|
|
||||||
vfs.umount('/sd') # eject
|
os.umount('/sd') # eject
|
||||||
|
|
||||||
RMT
|
RMT
|
||||||
---
|
---
|
||||||
@ -682,7 +481,7 @@ The RMT is ESP32-specific and allows generation of accurate digital pulses with
|
|||||||
r = esp32.RMT(0, pin=Pin(18), clock_div=8)
|
r = esp32.RMT(0, pin=Pin(18), clock_div=8)
|
||||||
r # RMT(channel=0, pin=18, source_freq=80000000, clock_div=8)
|
r # RMT(channel=0, pin=18, source_freq=80000000, clock_div=8)
|
||||||
# The channel resolution is 100ns (1/(source_freq/clock_div)).
|
# 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
|
r.write_pulses((1, 20, 2, 40), start=0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns
|
||||||
|
|
||||||
OneWire driver
|
OneWire driver
|
||||||
--------------
|
--------------
|
||||||
@ -735,16 +534,17 @@ The APA106 driver extends NeoPixel, but internally uses a different colour order
|
|||||||
ap = APA106(pin, 8)
|
ap = APA106(pin, 8)
|
||||||
r, g, b = ap[0]
|
r, g, b = ap[0]
|
||||||
|
|
||||||
|
For low-level driving of a NeoPixel::
|
||||||
|
|
||||||
|
import esp
|
||||||
|
esp.neopixel_write(pin, grb_buf, is800khz)
|
||||||
|
|
||||||
.. Warning::
|
.. Warning::
|
||||||
By default ``NeoPixel`` is configured to control the more popular *800kHz*
|
By default ``NeoPixel`` is configured to control the more popular *800kHz*
|
||||||
units. It is possible to use alternative timing to control other (typically
|
units. It is possible to use alternative timing to control other (typically
|
||||||
400kHz) devices by passing ``timing=0`` when constructing the
|
400kHz) devices by passing ``timing=0`` when constructing the
|
||||||
``NeoPixel`` object.
|
``NeoPixel`` object.
|
||||||
|
|
||||||
For low-level driving of a NeoPixel see `machine.bitstream`.
|
|
||||||
This low-level driver uses an RMT channel by default. To configure this see
|
|
||||||
`RMT.bitstream_channel`.
|
|
||||||
|
|
||||||
APA102 (DotStar) uses a different driver as it has an additional clock pin.
|
APA102 (DotStar) uses a different driver as it has an additional clock pin.
|
||||||
|
|
||||||
Capacitive touch
|
Capacitive touch
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 200 KiB |
@ -1,23 +0,0 @@
|
|||||||
.. _esp32_tutorial:
|
|
||||||
|
|
||||||
MicroPython tutorial for ESP32
|
|
||||||
==============================
|
|
||||||
|
|
||||||
This tutorial is intended to get you started using MicroPython on the ESP32
|
|
||||||
system-on-a-chip. If it is your first time it is recommended to follow the
|
|
||||||
tutorial through in the order below. Otherwise the sections are mostly self
|
|
||||||
contained, so feel free to skip to those that interest you.
|
|
||||||
|
|
||||||
The tutorial does not assume that you know Python, but it also does not attempt
|
|
||||||
to explain any of the details of the Python language. Instead it provides you
|
|
||||||
with commands that are ready to run, and hopes that you will gain a bit of
|
|
||||||
Python knowledge along the way. To learn more about Python itself please refer
|
|
||||||
to `<https://www.python.org>`__.
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 1
|
|
||||||
:numbered:
|
|
||||||
|
|
||||||
intro.rst
|
|
||||||
pwm.rst
|
|
||||||
peripheral_access.rst
|
|
||||||
@ -17,7 +17,7 @@ Requirements
|
|||||||
The first thing you need is a board with an ESP32 chip. The MicroPython
|
The first thing you need is a board with an ESP32 chip. The MicroPython
|
||||||
software supports the ESP32 chip itself and any board should work. The main
|
software supports the ESP32 chip itself and any board should work. The main
|
||||||
characteristic of a board is how the GPIO pins are connected to the outside
|
characteristic of a board is how the GPIO pins are connected to the outside
|
||||||
world, and whether it includes a built-in USB-serial converter to make the
|
world, and whether it includes a built-in USB-serial convertor to make the
|
||||||
UART available to your PC.
|
UART available to your PC.
|
||||||
|
|
||||||
Names of pins will be given in this tutorial using the chip names (eg GPIO2)
|
Names of pins will be given in this tutorial using the chip names (eg GPIO2)
|
||||||
@ -59,7 +59,7 @@ bootloader mode, and second you need to copy across the firmware. The exact
|
|||||||
procedure for these steps is highly dependent on the particular board and you will
|
procedure for these steps is highly dependent on the particular board and you will
|
||||||
need to refer to its documentation for details.
|
need to refer to its documentation for details.
|
||||||
|
|
||||||
Fortunately, most boards have a USB connector, a USB-serial converter, and the DTR
|
Fortunately, most boards have a USB connector, a USB-serial convertor, and the DTR
|
||||||
and RTS pins wired in a special way then deploying the firmware should be easy as
|
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
|
all steps can be done automatically. Boards that have such features
|
||||||
include the Adafruit Feather HUZZAH32, M5Stack, Wemos LOLIN32, and TinyPICO
|
include the Adafruit Feather HUZZAH32, M5Stack, Wemos LOLIN32, and TinyPICO
|
||||||
@ -104,7 +104,7 @@ Serial prompt
|
|||||||
|
|
||||||
Once you have the firmware on the device you can access the REPL (Python prompt)
|
Once you have the firmware on the device you can access the REPL (Python prompt)
|
||||||
over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial
|
over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial
|
||||||
converter, depending on your board. The baudrate is 115200.
|
convertor, depending on your board. The baudrate is 115200.
|
||||||
|
|
||||||
From here you can now follow the ESP8266 tutorial, because these two Espressif chips
|
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
|
are very similar when it comes to using MicroPython on them. The ESP8266 tutorial
|
||||||
@ -124,7 +124,7 @@ after it, here are troubleshooting recommendations:
|
|||||||
|
|
||||||
* The flashing instructions above use flashing speed of 460800 baud, which is
|
* The flashing instructions above use flashing speed of 460800 baud, which is
|
||||||
good compromise between speed and stability. However, depending on your
|
good compromise between speed and stability. However, depending on your
|
||||||
module/board, USB-UART converter, cables, host OS, etc., the above baud
|
module/board, USB-UART convertor, cables, host OS, etc., the above baud
|
||||||
rate may be too high and lead to errors. Try a more common 115200 baud
|
rate may be too high and lead to errors. Try a more common 115200 baud
|
||||||
rate instead in such cases.
|
rate instead in such cases.
|
||||||
|
|
||||||
|
|||||||
@ -1,136 +0,0 @@
|
|||||||
Accessing peripherals directly via registers
|
|
||||||
============================================
|
|
||||||
|
|
||||||
The ESP32's peripherals can be controlled via direct register reads and writes.
|
|
||||||
This requires reading the datasheet to know what registers to use and what
|
|
||||||
values to write to them. The following example shows how to turn on and change
|
|
||||||
the prescaler of the MCPWM0 peripheral.
|
|
||||||
|
|
||||||
.. code-block:: python3
|
|
||||||
|
|
||||||
from micropython import const
|
|
||||||
from machine import mem32
|
|
||||||
|
|
||||||
# Define the register addresses that will be used.
|
|
||||||
DR_REG_DPORT_BASE = const(0x3FF00000)
|
|
||||||
DPORT_PERIP_CLK_EN_REG = const(DR_REG_DPORT_BASE + 0x0C0)
|
|
||||||
DPORT_PERIP_RST_EN_REG = const(DR_REG_DPORT_BASE + 0x0C4)
|
|
||||||
DPORT_PWM0_CLK_EN = const(1 << 17)
|
|
||||||
MCPWM0 = const(0x3FF5E000)
|
|
||||||
MCPWM1 = const(0x3FF6C000)
|
|
||||||
|
|
||||||
# Enable CLK and disable RST.
|
|
||||||
print(hex(mem32[DPORT_PERIP_CLK_EN_REG] & 0xffffffff))
|
|
||||||
print(hex(mem32[DPORT_PERIP_RST_EN_REG] & 0xffffffff))
|
|
||||||
mem32[DPORT_PERIP_CLK_EN_REG] |= DPORT_PWM0_CLK_EN
|
|
||||||
mem32[DPORT_PERIP_RST_EN_REG] &= ~DPORT_PWM0_CLK_EN
|
|
||||||
print(hex(mem32[DPORT_PERIP_CLK_EN_REG] & 0xffffffff))
|
|
||||||
print(hex(mem32[DPORT_PERIP_RST_EN_REG] & 0xffffffff))
|
|
||||||
|
|
||||||
# Change the MCPWM0 prescaler.
|
|
||||||
print(hex(mem32[MCPWM0])) # read PWM_CLK_CFG_REG (reset value = 0)
|
|
||||||
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:
|
|
||||||
|
|
||||||
- ``DPORT_PERI_CLK_EN_REG``: used to enable a peripheral clock
|
|
||||||
|
|
||||||
- ``DPORT_PERI_RST_EN_REG``: used to reset (or take out of reset) a peripheral
|
|
||||||
|
|
||||||
The MCPWM0 peripheral is in bit position 17 of the above two registers, hence
|
|
||||||
the value of ``DPORT_PWM0_CLK_EN``.
|
|
||||||
|
|
||||||
Synchronous access to pins directly via registers
|
|
||||||
-------------------------------------------------
|
|
||||||
|
|
||||||
The following code shows how to access pins directly via registers. It has been
|
|
||||||
tested on a generic ESP32 board. It configures pins 16, 17, 32 and 33 in output
|
|
||||||
mode via registers, and switches pin output values via registers. Pins 16 and
|
|
||||||
17 are switched simultaneously.
|
|
||||||
|
|
||||||
.. code-block:: python3
|
|
||||||
|
|
||||||
from micropython import const
|
|
||||||
from machine import mem32, Pin
|
|
||||||
|
|
||||||
GPIO_OUT_REG = const(0x3FF44004) # GPIO 0-31 output register
|
|
||||||
GPIO_OUT1_REG = const(0x3FF44010) # GPIO 32-39 output register
|
|
||||||
|
|
||||||
GPIO_ENABLE_REG = const(0x3FF44020) # GPIO 0-31 output enable register
|
|
||||||
GPIO_ENABLE1_REG = const(0x3FF4402C) # GPIO 32-39 output enable register
|
|
||||||
|
|
||||||
M16 = 1 << 16 # Pin(16) bit mask
|
|
||||||
M17 = 1 << 17 # Pin(17) bit mask
|
|
||||||
|
|
||||||
M32 = 1 << (32-32) # Pin(32) bit mask
|
|
||||||
M33 = 1 << (33-32) # Pin(33) bit mask
|
|
||||||
|
|
||||||
# Enable pin output mode like
|
|
||||||
# p16 = Pin(16, mode=Pin.OUT)
|
|
||||||
# p17 = Pin(17, mode=Pin.OUT)
|
|
||||||
# p32 = Pin(32, mode=Pin.OUT)
|
|
||||||
# p33 = Pin(33, mode=Pin.OUT)
|
|
||||||
mem32[GPIO_ENABLE_REG] = mem32[GPIO_ENABLE_REG] | M16 | M17
|
|
||||||
mem32[GPIO_ENABLE1_REG] = mem32[GPIO_ENABLE1_REG] | M32 | M33
|
|
||||||
|
|
||||||
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
|
|
||||||
|
|
||||||
# Set outputs to 1 like
|
|
||||||
# p16(1)
|
|
||||||
# p17(1)
|
|
||||||
# p32(1)
|
|
||||||
# p33(1)
|
|
||||||
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] | M16 | M17
|
|
||||||
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] | M32 | M33
|
|
||||||
|
|
||||||
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
|
|
||||||
|
|
||||||
# Set outputs to 0 like
|
|
||||||
# p16(0)
|
|
||||||
# p17(0)
|
|
||||||
# p32(0)
|
|
||||||
# p33(0)
|
|
||||||
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] & ~(M16 | M17)
|
|
||||||
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] & ~(M32 | M33)
|
|
||||||
|
|
||||||
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
|
|
||||||
|
|
||||||
while True:
|
|
||||||
# Set outputs to 1
|
|
||||||
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] | M16 | M17
|
|
||||||
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] | M32 | M33
|
|
||||||
|
|
||||||
# Set outputs to 0
|
|
||||||
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] & ~(M16 | M17)
|
|
||||||
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] & ~(M32 | M33)
|
|
||||||
|
|
||||||
|
|
||||||
Output is::
|
|
||||||
|
|
||||||
0x0 0x0
|
|
||||||
0x30000 0x3
|
|
||||||
0x0 0x0
|
|
||||||
|
|
||||||
Pins 16 and 17 are switched synchronously:
|
|
||||||
|
|
||||||
.. image:: img/mem32_gpio_output.jpg
|
|
||||||
|
|
||||||
Same image on pins 32 and 33.
|
|
||||||
|
|
||||||
Note that pins 34-36 and 39 are inputs only. Also pins 1 and 3 are Tx, Rx of the REPL UART,
|
|
||||||
pins 6-11 are connected to the built-in SPI flash.
|
|
||||||
@ -1,115 +0,0 @@
|
|||||||
.. _esp32_pwm:
|
|
||||||
|
|
||||||
Pulse Width Modulation
|
|
||||||
======================
|
|
||||||
|
|
||||||
Pulse width modulation (PWM) is a way to get an artificial analog output on a
|
|
||||||
digital pin. It achieves this by rapidly toggling the pin from low to high.
|
|
||||||
There are two parameters associated with this: the frequency of the toggling,
|
|
||||||
and the duty cycle. The duty cycle is defined to be how long the pin is high
|
|
||||||
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::
|
|
||||||
|
|
||||||
from machine import Pin, PWM
|
|
||||||
try:
|
|
||||||
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):
|
|
||||||
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:
|
|
||||||
try:
|
|
||||||
pwm.deinit()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
Output is::
|
|
||||||
|
|
||||||
PWM(Pin(15), freq=100, duty=64, resolution=10, mode=0, channel=0, timer=0)
|
|
||||||
PWM(Pin(2), freq=100, duty=128, resolution=10, mode=0, channel=1, timer=0)
|
|
||||||
PWM(Pin(4), freq=200, duty=192, resolution=10, mode=0, channel=2, timer=1)
|
|
||||||
PWM(Pin(16), freq=200, duty=256, resolution=10, mode=0, channel=3, timer=1)
|
|
||||||
PWM(Pin(18), freq=300, duty=320, resolution=10, mode=0, channel=4, timer=2)
|
|
||||||
PWM(Pin(19), freq=300, duty=384, resolution=10, mode=0, channel=5, timer=2)
|
|
||||||
PWM(Pin(22), freq=400, duty=448, resolution=10, mode=0, channel=6, timer=3)
|
|
||||||
PWM(Pin(23), freq=400, duty=512, resolution=10, mode=0, channel=7, timer=3)
|
|
||||||
PWM(Pin(25), freq=500, duty=576, resolution=10, mode=1, channel=0, timer=0)
|
|
||||||
PWM(Pin(26), freq=500, duty=640, resolution=10, mode=1, channel=1, timer=0)
|
|
||||||
PWM(Pin(27), freq=600, duty=704, resolution=10, mode=1, channel=2, timer=1)
|
|
||||||
PWM(Pin(14), freq=600, duty=768, resolution=10, mode=1, channel=3, timer=1)
|
|
||||||
PWM(Pin(12), freq=700, duty=832, resolution=10, mode=1, channel=4, timer=2)
|
|
||||||
PWM(Pin(13), freq=700, duty=896, resolution=10, mode=1, channel=5, timer=2)
|
|
||||||
PWM(Pin(32), freq=800, duty=960, resolution=10, mode=1, channel=6, timer=3)
|
|
||||||
PWM(Pin(33), freq=800, duty=1023, resolution=10, mode=1, channel=7, timer=3)
|
|
||||||
|
|
||||||
* Example of a smooth frequency change::
|
|
||||||
|
|
||||||
from time import sleep
|
|
||||||
from machine import Pin, PWM
|
|
||||||
|
|
||||||
F_MIN = 500
|
|
||||||
F_MAX = 1000
|
|
||||||
|
|
||||||
f = F_MIN
|
|
||||||
delta_f = 1
|
|
||||||
|
|
||||||
p = PWM(Pin(5), f)
|
|
||||||
print(p)
|
|
||||||
|
|
||||||
while True:
|
|
||||||
p.freq(f)
|
|
||||||
|
|
||||||
sleep(10 / F_MIN)
|
|
||||||
|
|
||||||
f += delta_f
|
|
||||||
if f >= F_MAX or f <= F_MIN:
|
|
||||||
delta_f = -delta_f
|
|
||||||
|
|
||||||
See PWM wave at Pin(5) with an oscilloscope.
|
|
||||||
|
|
||||||
* Example of a smooth duty change::
|
|
||||||
|
|
||||||
from time import sleep
|
|
||||||
from machine import Pin, PWM
|
|
||||||
|
|
||||||
DUTY_MAX = 2**16 - 1
|
|
||||||
|
|
||||||
duty_u16 = 0
|
|
||||||
delta_d = 16
|
|
||||||
|
|
||||||
p = PWM(Pin(5), 1000, duty_u16=duty_u16)
|
|
||||||
print(p)
|
|
||||||
|
|
||||||
while True:
|
|
||||||
p.duty_u16(duty_u16)
|
|
||||||
|
|
||||||
sleep(1 / 1000)
|
|
||||||
|
|
||||||
duty_u16 += delta_d
|
|
||||||
if duty_u16 >= DUTY_MAX:
|
|
||||||
duty_u16 = DUTY_MAX
|
|
||||||
delta_d = -delta_d
|
|
||||||
elif duty_u16 <= 0:
|
|
||||||
duty_u16 = 0
|
|
||||||
delta_d = -delta_d
|
|
||||||
|
|
||||||
See PWM wave at Pin(5) with an oscilloscope.
|
|
||||||
|
|
||||||
Note: the Pin.OUT mode does not need to be specified. The channel is initialized
|
|
||||||
to PWM mode internally once for each Pin that is passed to the PWM constructor.
|
|
||||||
|
|
||||||
The following code is wrong::
|
|
||||||
|
|
||||||
pwm = PWM(Pin(5, Pin.OUT), freq=1000, duty=512) # Pin(5) in PWM mode here
|
|
||||||
pwm = PWM(Pin(5, Pin.OUT), freq=500, duty=256) # Pin(5) in OUT mode here, PWM is off
|
|
||||||
|
|
||||||
Use this code instead::
|
|
||||||
|
|
||||||
pwm = PWM(Pin(5), freq=1000, duty=512)
|
|
||||||
pwm.init(freq=500, duty=256)
|
|
||||||
@ -57,13 +57,13 @@ The :mod:`network` module::
|
|||||||
wlan.active(True) # activate the interface
|
wlan.active(True) # activate the interface
|
||||||
wlan.scan() # scan for access points
|
wlan.scan() # scan for access points
|
||||||
wlan.isconnected() # check if the station is connected to an AP
|
wlan.isconnected() # check if the station is connected to an AP
|
||||||
wlan.connect('ssid', 'key') # connect to an AP
|
wlan.connect('essid', 'password') # connect to an AP
|
||||||
wlan.config('mac') # get the interface's MAC address
|
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.AP_IF) # create access-point interface
|
ap = network.WLAN(network.AP_IF) # create access-point interface
|
||||||
ap.active(True) # activate the interface
|
ap.active(True) # activate the interface
|
||||||
ap.config(ssid='ESP-AP') # set the SSID of the access point
|
ap.config(essid='ESP-AP') # set the ESSID of the access point
|
||||||
|
|
||||||
A useful function for connecting to your local WiFi network is::
|
A useful function for connecting to your local WiFi network is::
|
||||||
|
|
||||||
@ -73,10 +73,10 @@ A useful function for connecting to your local WiFi network is::
|
|||||||
wlan.active(True)
|
wlan.active(True)
|
||||||
if not wlan.isconnected():
|
if not wlan.isconnected():
|
||||||
print('connecting to network...')
|
print('connecting to network...')
|
||||||
wlan.connect('ssid', 'key')
|
wlan.connect('essid', 'password')
|
||||||
while not wlan.isconnected():
|
while not wlan.isconnected():
|
||||||
pass
|
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
|
Once the network is established the :mod:`socket <socket>` module can be used
|
||||||
to create and use TCP/UDP sockets as usual.
|
to create and use TCP/UDP sockets as usual.
|
||||||
@ -374,13 +374,17 @@ Use the ``neopixel`` module::
|
|||||||
np.write() # write data to all pixels
|
np.write() # write data to all pixels
|
||||||
r, g, b = np[0] # get first pixel colour
|
r, g, b = np[0] # get first pixel colour
|
||||||
|
|
||||||
|
For low-level driving of a NeoPixel::
|
||||||
|
|
||||||
|
import esp
|
||||||
|
esp.neopixel_write(pin, grb_buf, is800khz)
|
||||||
|
|
||||||
.. Warning::
|
.. Warning::
|
||||||
By default ``NeoPixel`` is configured to control the more popular *800kHz*
|
By default ``NeoPixel`` is configured to control the more popular *800kHz*
|
||||||
units. It is possible to use alternative timing to control other (typically
|
units. It is possible to use alternative timing to control other (typically
|
||||||
400kHz) devices by passing ``timing=0`` when constructing the
|
400kHz) devices by passing ``timing=0`` when constructing the
|
||||||
``NeoPixel`` object.
|
``NeoPixel`` object.
|
||||||
|
|
||||||
For low-level driving of a NeoPixel see `machine.bitstream`.
|
|
||||||
|
|
||||||
APA102 driver
|
APA102 driver
|
||||||
-------------
|
-------------
|
||||||
|
|||||||
@ -18,12 +18,12 @@ The first thing you need is a board with an ESP8266 chip. The MicroPython
|
|||||||
software supports the ESP8266 chip itself and any board should work. The main
|
software supports the ESP8266 chip itself and any board should work. The main
|
||||||
characteristic of a board is how much flash it has, how the GPIO pins are
|
characteristic of a board is how much flash it has, how the GPIO pins are
|
||||||
connected to the outside world, and whether it includes a built-in USB-serial
|
connected to the outside world, and whether it includes a built-in USB-serial
|
||||||
converter to make the UART available to your PC.
|
convertor to make the UART available to your PC.
|
||||||
|
|
||||||
The minimum requirement for flash size is 1Mbyte. There is also a special
|
The minimum requirement for flash size is 1Mbyte. There is also a special
|
||||||
build for boards with 512KB, but it is highly limited comparing to the
|
build for boards with 512KB, but it is highly limited comparing to the
|
||||||
normal build: there is no support for filesystem, and thus features which
|
normal build: there is no support for filesystem, and thus features which
|
||||||
depend on it won't work (WebREPL, mip, etc.). As such, 512KB build will
|
depend on it won't work (WebREPL, upip, etc.). As such, 512KB build will
|
||||||
be more interesting for users who build from source and fine-tune parameters
|
be more interesting for users who build from source and fine-tune parameters
|
||||||
for their particular application.
|
for their particular application.
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ need to put your device in boot-loader mode, and second you need to copy across
|
|||||||
the firmware. The exact procedure for these steps is highly dependent on the
|
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.
|
particular board and you will need to refer to its documentation for details.
|
||||||
|
|
||||||
If you have a board that has a USB connector, a USB-serial converter, and has
|
If you have a board that has a USB connector, a USB-serial convertor, and has
|
||||||
the DTR and RTS pins wired in a special way then deploying the firmware should
|
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
|
be easy as all steps can be done automatically. Boards that have such features
|
||||||
include the Adafruit Feather HUZZAH and NodeMCU boards.
|
include the Adafruit Feather HUZZAH and NodeMCU boards.
|
||||||
@ -128,7 +128,7 @@ Serial prompt
|
|||||||
|
|
||||||
Once you have the firmware on the device you can access the REPL (Python prompt)
|
Once you have the firmware on the device you can access the REPL (Python prompt)
|
||||||
over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial
|
over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial
|
||||||
converter, depending on your board. The baudrate is 115200. The next part of
|
convertor, depending on your board. The baudrate is 115200. The next part of
|
||||||
the tutorial will discuss the prompt in more detail.
|
the tutorial will discuss the prompt in more detail.
|
||||||
|
|
||||||
WiFi
|
WiFi
|
||||||
@ -137,7 +137,7 @@ WiFi
|
|||||||
After a fresh install and boot the device configures itself as a WiFi access
|
After a fresh install and boot the device configures itself as a WiFi access
|
||||||
point (AP) that you can connect to. The ESSID is of the form MicroPython-xxxxxx
|
point (AP) that you can connect to. The ESSID is of the form MicroPython-xxxxxx
|
||||||
where the x's are replaced with part of the MAC address of your device (so will
|
where the x's are replaced with part of the MAC address of your device (so will
|
||||||
be the same every time, and most likely different for all ESP8266 chips). The
|
be the same everytime, and most likely different for all ESP8266 chips). The
|
||||||
password for the WiFi is micropythoN (note the upper-case N). Its IP address
|
password for the WiFi is micropythoN (note the upper-case N). Its IP address
|
||||||
will be 192.168.4.1 once you connect to its network. WiFi configuration will
|
will be 192.168.4.1 once you connect to its network. WiFi configuration will
|
||||||
be discussed in more detail later in the tutorial.
|
be discussed in more detail later in the tutorial.
|
||||||
@ -169,7 +169,7 @@ after it, here are troubleshooting recommendations:
|
|||||||
|
|
||||||
* The flashing instructions above use flashing speed of 460800 baud, which is
|
* The flashing instructions above use flashing speed of 460800 baud, which is
|
||||||
good compromise between speed and stability. However, depending on your
|
good compromise between speed and stability. However, depending on your
|
||||||
module/board, USB-UART converter, cables, host OS, etc., the above baud
|
module/board, USB-UART convertor, cables, host OS, etc., the above baud
|
||||||
rate may be too high and lead to errors. Try a more common 115200 baud
|
rate may be too high and lead to errors. Try a more common 115200 baud
|
||||||
rate instead in such cases.
|
rate instead in such cases.
|
||||||
|
|
||||||
|
|||||||
@ -19,10 +19,10 @@ You can check if the interfaces are active by::
|
|||||||
|
|
||||||
You can also check the network settings of the interface by::
|
You can also check the network settings of the interface by::
|
||||||
|
|
||||||
>>> ap_if.ipconfig('addr4')
|
>>> ap_if.ifconfig()
|
||||||
('192.168.4.1', '255.255.255.0')
|
('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
|
Configuration of the WiFi
|
||||||
-------------------------
|
-------------------------
|
||||||
@ -37,7 +37,7 @@ First activate the station interface::
|
|||||||
|
|
||||||
Then connect to your WiFi network::
|
Then connect to your WiFi network::
|
||||||
|
|
||||||
>>> sta_if.connect('<your SSID>', '<your key>')
|
>>> sta_if.connect('<your ESSID>', '<your password>')
|
||||||
|
|
||||||
To check if the connection is established use::
|
To check if the connection is established use::
|
||||||
|
|
||||||
@ -45,8 +45,8 @@ To check if the connection is established use::
|
|||||||
|
|
||||||
Once established you can check the IP address::
|
Once established you can check the IP address::
|
||||||
|
|
||||||
>>> sta_if.ipconfig('addr4')
|
>>> sta_if.ifconfig()
|
||||||
('192.168.0.2', '255.255.255.0')
|
('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::
|
You can then disable the access-point interface if you no longer need it::
|
||||||
|
|
||||||
@ -61,10 +61,10 @@ connect to your WiFi network::
|
|||||||
if not sta_if.isconnected():
|
if not sta_if.isconnected():
|
||||||
print('connecting to network...')
|
print('connecting to network...')
|
||||||
sta_if.active(True)
|
sta_if.active(True)
|
||||||
sta_if.connect('<ssid>', '<key>')
|
sta_if.connect('<essid>', '<password>')
|
||||||
while not sta_if.isconnected():
|
while not sta_if.isconnected():
|
||||||
pass
|
pass
|
||||||
print('network config:', sta_if.ipconfig('addr4'))
|
print('network config:', sta_if.ifconfig())
|
||||||
|
|
||||||
Sockets
|
Sockets
|
||||||
-------
|
-------
|
||||||
|
|||||||
@ -13,7 +13,7 @@ REPL over the serial port
|
|||||||
|
|
||||||
The REPL is always available on the UART0 serial peripheral, which is connected
|
The REPL is always available on the UART0 serial peripheral, which is connected
|
||||||
to the pins GPIO1 for TX and GPIO3 for RX. The baudrate of the REPL is 115200.
|
to the pins GPIO1 for TX and GPIO3 for RX. The baudrate of the REPL is 115200.
|
||||||
If your board has a USB-serial converter on it then you should be able to access
|
If your board has a USB-serial convertor on it then you should be able to access
|
||||||
the REPL directly from your PC. Otherwise you will need to have a way of
|
the REPL directly from your PC. Otherwise you will need to have a way of
|
||||||
communicating with the UART.
|
communicating with the UART.
|
||||||
|
|
||||||
|
|||||||
@ -66,8 +66,8 @@ Subclassing FrameBuffer provides support for graphics primitives::
|
|||||||
display.hline(0, 8, 4, 1) # draw horizontal line x=0, y=8, width=4, colour=1
|
display.hline(0, 8, 4, 1) # draw horizontal line x=0, y=8, width=4, colour=1
|
||||||
display.vline(0, 8, 4, 1) # draw vertical line x=0, y=8, height=4, colour=1
|
display.vline(0, 8, 4, 1) # draw vertical line x=0, y=8, height=4, colour=1
|
||||||
display.line(0, 0, 127, 63, 1) # draw a line from 0,0 to 127,63
|
display.line(0, 0, 127, 63, 1) # draw a line from 0,0 to 127,63
|
||||||
display.rect(10, 10, 107, 43, 1) # draw a rectangle outline 10,10 to 117,53, colour=1
|
display.rect(10, 10, 107, 43, 1) # draw a rectangle outline 10,10 to 107,43, colour=1
|
||||||
display.fill_rect(10, 10, 107, 43, 1) # draw a solid rectangle 10,10 to 117,53, colour=1
|
display.fill_rect(10, 10, 107, 43, 1) # draw a solid rectangle 10,10 to 107,43, colour=1
|
||||||
display.text('Hello World', 0, 0, 1) # draw some text at x=0, y=0, colour=1
|
display.text('Hello World', 0, 0, 1) # draw some text at x=0, y=0, colour=1
|
||||||
display.scroll(20, 0) # scroll 20 pixels to the right
|
display.scroll(20, 0) # scroll 20 pixels to the right
|
||||||
|
|
||||||
|
|||||||
@ -12,9 +12,6 @@ MicroPython documentation and references
|
|||||||
esp8266/quickref.rst
|
esp8266/quickref.rst
|
||||||
esp32/quickref.rst
|
esp32/quickref.rst
|
||||||
rp2/quickref.rst
|
rp2/quickref.rst
|
||||||
mimxrt/quickref.rst
|
|
||||||
wipy/quickref.rst
|
wipy/quickref.rst
|
||||||
unix/quickref.rst
|
unix/quickref.rst
|
||||||
zephyr/quickref.rst
|
zephyr/quickref.rst
|
||||||
renesas-ra/quickref.rst
|
|
||||||
samd/quickref.rst
|
|
||||||
|
|||||||
@ -27,55 +27,3 @@ Classes
|
|||||||
|
|
||||||
Append new elements as contained in *iterable* to the end of
|
Append new elements as contained in *iterable* to the end of
|
||||||
array, growing it.
|
array, growing it.
|
||||||
|
|
||||||
.. method:: __getitem__(index)
|
|
||||||
|
|
||||||
Indexed read of the array, called as ``a[index]`` (where ``a`` is an ``array``).
|
|
||||||
Returns a value if *index* is an ``int`` and an ``array`` if *index* is a slice.
|
|
||||||
Negative indices count from the end and ``IndexError`` is thrown if the index is
|
|
||||||
out of range.
|
|
||||||
|
|
||||||
**Note:** ``__getitem__`` cannot be called directly (``a.__getitem__(index)`` fails) and
|
|
||||||
is not present in ``__dict__``, however ``a[index]`` does work.
|
|
||||||
|
|
||||||
.. method:: __setitem__(index, value)
|
|
||||||
|
|
||||||
Indexed write into the array, called as ``a[index] = value`` (where ``a`` is an ``array``).
|
|
||||||
``value`` is a single value if *index* is an ``int`` and an ``array`` if *index* is a slice.
|
|
||||||
Negative indices count from the end and ``IndexError`` is thrown if the index is out of range.
|
|
||||||
|
|
||||||
**Note:** ``__setitem__`` cannot be called directly (``a.__setitem__(index, value)`` fails) and
|
|
||||||
is not present in ``__dict__``, however ``a[index] = value`` does work.
|
|
||||||
|
|
||||||
.. method:: __len__()
|
|
||||||
|
|
||||||
Returns the number of items in the array, called as ``len(a)`` (where ``a`` is an ``array``).
|
|
||||||
|
|
||||||
**Note:** ``__len__`` cannot be called directly (``a.__len__()`` fails) and the
|
|
||||||
method is not present in ``__dict__``, however ``len(a)`` does work.
|
|
||||||
|
|
||||||
.. method:: __add__(other)
|
|
||||||
|
|
||||||
Return a new ``array`` that is the concatenation of the array with *other*, called as
|
|
||||||
``a + other`` (where ``a`` and *other* are both ``arrays``).
|
|
||||||
|
|
||||||
**Note:** ``__add__`` cannot be called directly (``a.__add__(other)`` fails) and
|
|
||||||
is not present in ``__dict__``, however ``a + other`` does work.
|
|
||||||
|
|
||||||
.. method:: __iadd__(other)
|
|
||||||
|
|
||||||
Concatenates the array with *other* in-place, called as ``a += other`` (where ``a`` and *other*
|
|
||||||
are both ``arrays``). Equivalent to ``extend(other)``.
|
|
||||||
|
|
||||||
**Note:** ``__iadd__`` cannot be called directly (``a.__iadd__(other)`` fails) and
|
|
||||||
is not present in ``__dict__``, however ``a += other`` does work.
|
|
||||||
|
|
||||||
.. method:: __repr__()
|
|
||||||
|
|
||||||
Returns the string representation of the array, called as ``str(a)`` or ``repr(a)```
|
|
||||||
(where ``a`` is an ``array``). Returns the string ``"array(<type>, [<elements>])"``,
|
|
||||||
where ``<type>`` is the type code letter for the array and ``<elements>`` is a comma
|
|
||||||
separated list of the elements of the array.
|
|
||||||
|
|
||||||
**Note:** ``__repr__`` cannot be called directly (``a.__repr__()`` fails) and
|
|
||||||
is not present in ``__dict__``, however ``str(a)`` and ``repr(a)`` both work.
|
|
||||||
|
|||||||
@ -1,363 +0,0 @@
|
|||||||
:mod:`asyncio` --- asynchronous I/O scheduler
|
|
||||||
=============================================
|
|
||||||
|
|
||||||
.. module:: asyncio
|
|
||||||
:synopsis: asynchronous I/O scheduler for writing concurrent code
|
|
||||||
|
|
||||||
|see_cpython_module|
|
|
||||||
`asyncio <https://docs.python.org/3.8/library/asyncio.html>`_
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
import asyncio
|
|
||||||
|
|
||||||
async def blink(led, period_ms):
|
|
||||||
while True:
|
|
||||||
led.on()
|
|
||||||
await asyncio.sleep_ms(5)
|
|
||||||
led.off()
|
|
||||||
await asyncio.sleep_ms(period_ms)
|
|
||||||
|
|
||||||
async def main(led1, led2):
|
|
||||||
asyncio.create_task(blink(led1, 700))
|
|
||||||
asyncio.create_task(blink(led2, 400))
|
|
||||||
await asyncio.sleep_ms(10_000)
|
|
||||||
|
|
||||||
# Running on a pyboard
|
|
||||||
from pyb import LED
|
|
||||||
asyncio.run(main(LED(1), LED(2)))
|
|
||||||
|
|
||||||
# Running on a generic board
|
|
||||||
from machine import Pin
|
|
||||||
asyncio.run(main(Pin(1), Pin(2)))
|
|
||||||
|
|
||||||
Core functions
|
|
||||||
--------------
|
|
||||||
|
|
||||||
.. function:: create_task(coro)
|
|
||||||
|
|
||||||
Create a new task from the given coroutine and schedule it to run.
|
|
||||||
|
|
||||||
Returns the corresponding `Task` object.
|
|
||||||
|
|
||||||
.. function:: current_task()
|
|
||||||
|
|
||||||
Return the `Task` object associated with the currently running task.
|
|
||||||
|
|
||||||
.. function:: run(coro)
|
|
||||||
|
|
||||||
Create a new task from the given coroutine and run it until it completes.
|
|
||||||
|
|
||||||
Returns the value returned by *coro*.
|
|
||||||
|
|
||||||
.. function:: sleep(t)
|
|
||||||
|
|
||||||
Sleep for *t* seconds (can be a float).
|
|
||||||
|
|
||||||
This is a coroutine.
|
|
||||||
|
|
||||||
.. function:: sleep_ms(t)
|
|
||||||
|
|
||||||
Sleep for *t* milliseconds.
|
|
||||||
|
|
||||||
This is a coroutine, and a MicroPython extension.
|
|
||||||
|
|
||||||
Additional functions
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
.. function:: wait_for(awaitable, timeout)
|
|
||||||
|
|
||||||
Wait for the *awaitable* to complete, but cancel it if it takes longer
|
|
||||||
than *timeout* seconds. If *awaitable* is not a task then a task will be
|
|
||||||
created from it.
|
|
||||||
|
|
||||||
If a timeout occurs, it cancels the task and raises ``asyncio.TimeoutError``:
|
|
||||||
this should be trapped by the caller. The task receives
|
|
||||||
``asyncio.CancelledError`` which may be ignored or trapped using ``try...except``
|
|
||||||
or ``try...finally`` to run cleanup code.
|
|
||||||
|
|
||||||
Returns the return value of *awaitable*.
|
|
||||||
|
|
||||||
This is a coroutine.
|
|
||||||
|
|
||||||
.. function:: wait_for_ms(awaitable, timeout)
|
|
||||||
|
|
||||||
Similar to `wait_for` but *timeout* is an integer in milliseconds.
|
|
||||||
|
|
||||||
This is a coroutine, and a MicroPython extension.
|
|
||||||
|
|
||||||
.. function:: gather(*awaitables, return_exceptions=False)
|
|
||||||
|
|
||||||
Run all *awaitables* concurrently. Any *awaitables* that are not tasks are
|
|
||||||
promoted to tasks.
|
|
||||||
|
|
||||||
Returns a list of return values of all *awaitables*.
|
|
||||||
|
|
||||||
This is a coroutine.
|
|
||||||
|
|
||||||
class Task
|
|
||||||
----------
|
|
||||||
|
|
||||||
.. class:: Task()
|
|
||||||
|
|
||||||
This object wraps a coroutine into a running task. Tasks can be waited on
|
|
||||||
using ``await task``, which will wait for the task to complete and return
|
|
||||||
the return value of the task.
|
|
||||||
|
|
||||||
Tasks should not be created directly, rather use `create_task` to create them.
|
|
||||||
|
|
||||||
.. method:: Task.cancel()
|
|
||||||
|
|
||||||
Cancel the task by injecting ``asyncio.CancelledError`` into it. The task may
|
|
||||||
ignore this exception. Cleanup code may be run by trapping it, or via
|
|
||||||
``try ... finally``.
|
|
||||||
|
|
||||||
class Event
|
|
||||||
-----------
|
|
||||||
|
|
||||||
.. class:: Event()
|
|
||||||
|
|
||||||
Create a new event which can be used to synchronise tasks. Events start
|
|
||||||
in the cleared state.
|
|
||||||
|
|
||||||
.. method:: Event.is_set()
|
|
||||||
|
|
||||||
Returns ``True`` if the event is set, ``False`` otherwise.
|
|
||||||
|
|
||||||
.. method:: Event.set()
|
|
||||||
|
|
||||||
Set the event. Any tasks waiting on the event will be scheduled to run.
|
|
||||||
|
|
||||||
Note: This must be called from within a task. It is not safe to call this
|
|
||||||
from an IRQ, scheduler callback, or other thread. See `ThreadSafeFlag`.
|
|
||||||
|
|
||||||
.. method:: Event.clear()
|
|
||||||
|
|
||||||
Clear the event.
|
|
||||||
|
|
||||||
.. method:: Event.wait()
|
|
||||||
|
|
||||||
Wait for the event to be set. If the event is already set then it returns
|
|
||||||
immediately.
|
|
||||||
|
|
||||||
This is a coroutine.
|
|
||||||
|
|
||||||
class ThreadSafeFlag
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
.. class:: ThreadSafeFlag()
|
|
||||||
|
|
||||||
Create a new flag which can be used to synchronise a task with code running
|
|
||||||
outside the asyncio loop, such as other threads, IRQs, or scheduler
|
|
||||||
callbacks. Flags start in the cleared state.
|
|
||||||
|
|
||||||
.. method:: ThreadSafeFlag.set()
|
|
||||||
|
|
||||||
Set the flag. If there is a task waiting on the flag, it will be scheduled
|
|
||||||
to run.
|
|
||||||
|
|
||||||
.. method:: ThreadSafeFlag.clear()
|
|
||||||
|
|
||||||
Clear the flag. This may be used to ensure that a possibly previously-set
|
|
||||||
flag is clear before waiting for it.
|
|
||||||
|
|
||||||
.. method:: ThreadSafeFlag.wait()
|
|
||||||
|
|
||||||
Wait for the flag to be set. If the flag is already set then it returns
|
|
||||||
immediately. The flag is automatically reset upon return from ``wait``.
|
|
||||||
|
|
||||||
A flag may only be waited on by a single task at a time.
|
|
||||||
|
|
||||||
This is a coroutine.
|
|
||||||
|
|
||||||
class Lock
|
|
||||||
----------
|
|
||||||
|
|
||||||
.. class:: Lock()
|
|
||||||
|
|
||||||
Create a new lock which can be used to coordinate tasks. Locks start in
|
|
||||||
the unlocked state.
|
|
||||||
|
|
||||||
In addition to the methods below, locks can be used in an ``async with`` statement.
|
|
||||||
|
|
||||||
.. method:: Lock.locked()
|
|
||||||
|
|
||||||
Returns ``True`` if the lock is locked, otherwise ``False``.
|
|
||||||
|
|
||||||
.. method:: Lock.acquire()
|
|
||||||
|
|
||||||
Wait for the lock to be in the unlocked state and then lock it in an atomic
|
|
||||||
way. Only one task can acquire the lock at any one time.
|
|
||||||
|
|
||||||
This is a coroutine.
|
|
||||||
|
|
||||||
.. method:: Lock.release()
|
|
||||||
|
|
||||||
Release the lock. If any tasks are waiting on the lock then the next one in the
|
|
||||||
queue is scheduled to run and the lock remains locked. Otherwise, no tasks are
|
|
||||||
waiting an the lock becomes unlocked.
|
|
||||||
|
|
||||||
TCP stream connections
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
.. function:: open_connection(host, port, ssl=None)
|
|
||||||
|
|
||||||
Open a TCP connection to the given *host* and *port*. The *host* address will be
|
|
||||||
resolved using `socket.getaddrinfo`, which is currently a blocking call.
|
|
||||||
If *ssl* is a `ssl.SSLContext` object, this context is used to create the transport;
|
|
||||||
if *ssl* is ``True``, a default context is used.
|
|
||||||
|
|
||||||
Returns a pair of streams: a reader and a writer stream.
|
|
||||||
Will raise a socket-specific ``OSError`` if the host could not be resolved or if
|
|
||||||
the connection could not be made.
|
|
||||||
|
|
||||||
This is a coroutine.
|
|
||||||
|
|
||||||
.. function:: start_server(callback, host, port, backlog=5, ssl=None)
|
|
||||||
|
|
||||||
Start a TCP server on the given *host* and *port*. The *callback* will be
|
|
||||||
called with incoming, accepted connections, and be passed 2 arguments: reader
|
|
||||||
and writer streams for the connection.
|
|
||||||
|
|
||||||
If *ssl* is a `ssl.SSLContext` object, this context is used to create the transport.
|
|
||||||
|
|
||||||
Returns a `Server` object.
|
|
||||||
|
|
||||||
This is a coroutine.
|
|
||||||
|
|
||||||
.. class:: Stream()
|
|
||||||
|
|
||||||
This represents a TCP stream connection. To minimise code this class implements
|
|
||||||
both a reader and a writer, and both ``StreamReader`` and ``StreamWriter`` alias to
|
|
||||||
this class.
|
|
||||||
|
|
||||||
.. method:: Stream.get_extra_info(v)
|
|
||||||
|
|
||||||
Get extra information about the stream, given by *v*. The valid values for *v* are:
|
|
||||||
``peername``.
|
|
||||||
|
|
||||||
.. method:: Stream.close()
|
|
||||||
|
|
||||||
Close the stream.
|
|
||||||
|
|
||||||
.. method:: Stream.wait_closed()
|
|
||||||
|
|
||||||
Wait for the stream to close.
|
|
||||||
|
|
||||||
This is a coroutine.
|
|
||||||
|
|
||||||
.. method:: Stream.read(n=-1)
|
|
||||||
|
|
||||||
Read up to *n* bytes and return them. If *n* is not provided or -1 then read all
|
|
||||||
bytes until EOF. The returned value will be an empty bytes object if EOF is
|
|
||||||
encountered before any bytes are read.
|
|
||||||
|
|
||||||
This is a coroutine.
|
|
||||||
|
|
||||||
.. method:: Stream.readinto(buf)
|
|
||||||
|
|
||||||
Read up to n bytes into *buf* with n being equal to the length of *buf*.
|
|
||||||
|
|
||||||
Return the number of bytes read into *buf*.
|
|
||||||
|
|
||||||
This is a coroutine, and a MicroPython extension.
|
|
||||||
|
|
||||||
.. method:: Stream.readexactly(n)
|
|
||||||
|
|
||||||
Read exactly *n* bytes and return them as a bytes object.
|
|
||||||
|
|
||||||
Raises an ``EOFError`` exception if the stream ends before reading *n* bytes.
|
|
||||||
|
|
||||||
This is a coroutine.
|
|
||||||
|
|
||||||
.. method:: Stream.readline()
|
|
||||||
|
|
||||||
Read a line and return it.
|
|
||||||
|
|
||||||
This is a coroutine.
|
|
||||||
|
|
||||||
.. method:: Stream.write(buf)
|
|
||||||
|
|
||||||
Accumulated *buf* to the output buffer. The data is only flushed when
|
|
||||||
`Stream.drain` is called. It is recommended to call `Stream.drain` immediately
|
|
||||||
after calling this function.
|
|
||||||
|
|
||||||
.. method:: Stream.drain()
|
|
||||||
|
|
||||||
Drain (write) all buffered output data out to the stream.
|
|
||||||
|
|
||||||
This is a coroutine.
|
|
||||||
|
|
||||||
.. class:: Server()
|
|
||||||
|
|
||||||
This represents the server class returned from `start_server`. It can be used
|
|
||||||
in an ``async with`` statement to close the server upon exit.
|
|
||||||
|
|
||||||
.. method:: Server.close()
|
|
||||||
|
|
||||||
Close the server.
|
|
||||||
|
|
||||||
.. method:: Server.wait_closed()
|
|
||||||
|
|
||||||
Wait for the server to close.
|
|
||||||
|
|
||||||
This is a coroutine.
|
|
||||||
|
|
||||||
Event Loop
|
|
||||||
----------
|
|
||||||
|
|
||||||
.. function:: get_event_loop()
|
|
||||||
|
|
||||||
Return the event loop used to schedule and run tasks. See `Loop`.
|
|
||||||
|
|
||||||
.. function:: new_event_loop()
|
|
||||||
|
|
||||||
Reset the event loop and return it.
|
|
||||||
|
|
||||||
Note: since MicroPython only has a single event loop this function just
|
|
||||||
resets the loop's state, it does not create a new one.
|
|
||||||
|
|
||||||
.. class:: Loop()
|
|
||||||
|
|
||||||
This represents the object which schedules and runs tasks. It cannot be
|
|
||||||
created, use `get_event_loop` instead.
|
|
||||||
|
|
||||||
.. method:: Loop.create_task(coro)
|
|
||||||
|
|
||||||
Create a task from the given *coro* and return the new `Task` object.
|
|
||||||
|
|
||||||
.. method:: Loop.run_forever()
|
|
||||||
|
|
||||||
Run the event loop until `stop()` is called.
|
|
||||||
|
|
||||||
.. method:: Loop.run_until_complete(awaitable)
|
|
||||||
|
|
||||||
Run the given *awaitable* until it completes. If *awaitable* is not a task
|
|
||||||
then it will be promoted to one.
|
|
||||||
|
|
||||||
.. method:: Loop.stop()
|
|
||||||
|
|
||||||
Stop the event loop.
|
|
||||||
|
|
||||||
.. method:: Loop.close()
|
|
||||||
|
|
||||||
Close the event loop.
|
|
||||||
|
|
||||||
.. method:: Loop.set_exception_handler(handler)
|
|
||||||
|
|
||||||
Set the exception handler to call when a Task raises an exception that is not
|
|
||||||
caught. The *handler* should accept two arguments: ``(loop, context)``.
|
|
||||||
|
|
||||||
.. method:: Loop.get_exception_handler()
|
|
||||||
|
|
||||||
Get the current exception handler. Returns the handler, or ``None`` if no
|
|
||||||
custom handler is set.
|
|
||||||
|
|
||||||
.. method:: Loop.default_exception_handler(context)
|
|
||||||
|
|
||||||
The default exception handler that is called.
|
|
||||||
|
|
||||||
.. method:: Loop.call_exception_handler(context)
|
|
||||||
|
|
||||||
Call the current exception handler. The argument *context* is passed through and
|
|
||||||
is a dictionary containing keys: ``'message'``, ``'exception'``, ``'future'``.
|
|
||||||
@ -31,8 +31,8 @@ Functions
|
|||||||
Conforms to `RFC 2045 s.6.8 <https://tools.ietf.org/html/rfc2045#section-6.8>`_.
|
Conforms to `RFC 2045 s.6.8 <https://tools.ietf.org/html/rfc2045#section-6.8>`_.
|
||||||
Returns a bytes object.
|
Returns a bytes object.
|
||||||
|
|
||||||
.. function:: b2a_base64(data, *, newline=True)
|
.. function:: b2a_base64(data)
|
||||||
|
|
||||||
Encode binary data in base64 format, as in `RFC 3548
|
Encode binary data in base64 format, as in `RFC 3548
|
||||||
<https://tools.ietf.org/html/rfc3548.html>`_. Returns the encoded data
|
<https://tools.ietf.org/html/rfc3548.html>`_. Returns the encoded data
|
||||||
followed by a newline character if newline is true, as a bytes object.
|
followed by a newline character, as a bytes object.
|
||||||
|
|||||||
@ -13,9 +13,6 @@ concurrently. Pairing (and bonding) is supported on some ports.
|
|||||||
This API is intended to match the low-level Bluetooth protocol and provide
|
This API is intended to match the low-level Bluetooth protocol and provide
|
||||||
building-blocks for higher-level abstractions such as specific device types.
|
building-blocks for higher-level abstractions such as specific device types.
|
||||||
|
|
||||||
.. note:: For most applications, we recommend using the higher-level
|
|
||||||
`aioble library <https://github.com/micropython/micropython-lib/tree/master/micropython/bluetooth/aioble>`_.
|
|
||||||
|
|
||||||
.. note:: This module is still under development and its classes, functions,
|
.. note:: This module is still under development and its classes, functions,
|
||||||
methods and constants are subject to change.
|
methods and constants are subject to change.
|
||||||
|
|
||||||
@ -44,7 +41,7 @@ Configuration
|
|||||||
|
|
||||||
Get or set configuration values of the BLE interface. To get a value the
|
Get or set configuration values of the BLE interface. To get a value the
|
||||||
parameter name should be quoted as a string, and just one parameter is
|
parameter name should be quoted as a string, and just one parameter is
|
||||||
queried at a time. To set values use the keyword syntax, and one or more
|
queried at a time. To set values use the keyword syntax, and one ore more
|
||||||
parameter can be set at a time.
|
parameter can be set at a time.
|
||||||
|
|
||||||
Currently supported values are:
|
Currently supported values are:
|
||||||
@ -52,7 +49,7 @@ Configuration
|
|||||||
- ``'mac'``: The current address in use, depending on the current address mode.
|
- ``'mac'``: The current address in use, depending on the current address mode.
|
||||||
This returns a tuple of ``(addr_type, addr)``.
|
This returns a tuple of ``(addr_type, addr)``.
|
||||||
|
|
||||||
See :meth:`gatts_write <BLE.gatts_write>` for details about address type.
|
See :meth:`gatts_write <BLE.gap_scan>` for details about address type.
|
||||||
|
|
||||||
This may only be queried while the interface is currently active.
|
This may only be queried while the interface is currently active.
|
||||||
|
|
||||||
@ -166,7 +163,7 @@ Event Handling
|
|||||||
conn_handle, status = data
|
conn_handle, status = data
|
||||||
elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT:
|
elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT:
|
||||||
# Called for each characteristic found by gattc_discover_services().
|
# Called for each characteristic found by gattc_discover_services().
|
||||||
conn_handle, end_handle, value_handle, properties, uuid = data
|
conn_handle, def_handle, value_handle, properties, uuid = data
|
||||||
elif event == _IRQ_GATTC_CHARACTERISTIC_DONE:
|
elif event == _IRQ_GATTC_CHARACTERISTIC_DONE:
|
||||||
# Called once service discovery is complete.
|
# Called once service discovery is complete.
|
||||||
# Note: Status will be zero on success, implementation-specific value otherwise.
|
# Note: Status will be zero on success, implementation-specific value otherwise.
|
||||||
@ -183,10 +180,12 @@ Event Handling
|
|||||||
conn_handle, value_handle, char_data = data
|
conn_handle, value_handle, char_data = data
|
||||||
elif event == _IRQ_GATTC_READ_DONE:
|
elif event == _IRQ_GATTC_READ_DONE:
|
||||||
# A gattc_read() has completed.
|
# A gattc_read() has completed.
|
||||||
|
# Note: The value_handle will be zero on btstack (but present on NimBLE).
|
||||||
# Note: Status will be zero on success, implementation-specific value otherwise.
|
# Note: Status will be zero on success, implementation-specific value otherwise.
|
||||||
conn_handle, value_handle, status = data
|
conn_handle, value_handle, status = data
|
||||||
elif event == _IRQ_GATTC_WRITE_DONE:
|
elif event == _IRQ_GATTC_WRITE_DONE:
|
||||||
# A gattc_write() has completed.
|
# A gattc_write() has completed.
|
||||||
|
# Note: The value_handle will be zero on btstack (but present on NimBLE).
|
||||||
# Note: Status will be zero on success, implementation-specific value otherwise.
|
# Note: Status will be zero on success, implementation-specific value otherwise.
|
||||||
conn_handle, value_handle, status = data
|
conn_handle, value_handle, status = data
|
||||||
elif event == _IRQ_GATTC_NOTIFY:
|
elif event == _IRQ_GATTC_NOTIFY:
|
||||||
@ -312,7 +311,7 @@ Broadcaster Role (Advertiser)
|
|||||||
in all broadcasts, and *resp_data* is send in reply to an active scan.
|
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
|
**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)``.
|
broadcaster to resume advertising with just ``gap_advertise(interval_us)``.
|
||||||
To clear the advertising payload pass an empty ``bytes``, i.e. ``b''``.
|
To clear the advertising payload pass an empty ``bytes``, i.e. ``b''``.
|
||||||
|
|
||||||
@ -360,27 +359,13 @@ Central Role
|
|||||||
|
|
||||||
A central device can connect to peripherals that it has discovered using the observer role (see :meth:`gap_scan<BLE.gap_scan>`) or with a known address.
|
A central device can connect to peripherals that it has discovered using the observer role (see :meth:`gap_scan<BLE.gap_scan>`) or with a known address.
|
||||||
|
|
||||||
.. method:: BLE.gap_connect(addr_type, addr, scan_duration_ms=2000, min_conn_interval_us=None, max_conn_interval_us=None, /)
|
.. method:: BLE.gap_connect(addr_type, addr, scan_duration_ms=2000, /)
|
||||||
|
|
||||||
Connect to a peripheral.
|
Connect to a peripheral.
|
||||||
|
|
||||||
See :meth:`gap_scan <BLE.gap_scan>` for details about address types.
|
See :meth:`gap_scan <BLE.gap_scan>` for details about address types.
|
||||||
|
|
||||||
To cancel an outstanding connection attempt early, call
|
On success, the ``_IRQ_PERIPHERAL_CONNECT`` event will be raised.
|
||||||
``gap_connect(None)``.
|
|
||||||
|
|
||||||
On success, the ``_IRQ_PERIPHERAL_CONNECT`` event will be raised. If
|
|
||||||
cancelling a connection attempt, the ``_IRQ_PERIPHERAL_DISCONNECT`` event
|
|
||||||
will be raised.
|
|
||||||
|
|
||||||
The device will wait up to *scan_duration_ms* to receive an advertising
|
|
||||||
payload from the device.
|
|
||||||
|
|
||||||
The connection interval can be configured in **micro**\ seconds using either
|
|
||||||
or both of *min_conn_interval_us* and *max_conn_interval_us*. Otherwise a
|
|
||||||
default interval will be chosen, typically between 30000 and 50000
|
|
||||||
microseconds. A shorter interval will increase throughput, at the expense
|
|
||||||
of power usage.
|
|
||||||
|
|
||||||
|
|
||||||
Peripheral Role
|
Peripheral Role
|
||||||
@ -512,24 +497,19 @@ writes from a client to a given characteristic, use
|
|||||||
|
|
||||||
Sends a notification request to a connected client.
|
Sends a notification request to a connected client.
|
||||||
|
|
||||||
If *data* is ``None`` (the default), then the current local value (as set
|
If *data* is not ``None``, then that value is sent to the client as part of
|
||||||
with :meth:`gatts_write <BLE.gatts_write>`) will be sent.
|
the notification. The local value will not be modified.
|
||||||
|
|
||||||
Otherwise, if *data* is not ``None``, then that value is sent to the client
|
Otherwise, if *data* is ``None``, then the current local value (as
|
||||||
as part of the notification. The local value will not be modified.
|
set with :meth:`gatts_write <BLE.gatts_write>`) will be sent.
|
||||||
|
|
||||||
**Note:** The notification will be sent regardless of the subscription
|
**Note:** The notification will be sent regardless of the subscription
|
||||||
status of the client to this characteristic.
|
status of the client to this characteristic.
|
||||||
|
|
||||||
.. method:: BLE.gatts_indicate(conn_handle, value_handle, data=None, /)
|
.. method:: BLE.gatts_indicate(conn_handle, value_handle, /)
|
||||||
|
|
||||||
Sends a indication request to a connected client.
|
Sends an indication request containing the characteristic's current value to
|
||||||
|
a connected client.
|
||||||
If *data* is ``None`` (the default), then the current local value (as set
|
|
||||||
with :meth:`gatts_write <BLE.gatts_write>`) will be sent.
|
|
||||||
|
|
||||||
Otherwise, if *data* is not ``None``, then that value is sent to the client
|
|
||||||
as part of the indication. The local value will not be modified.
|
|
||||||
|
|
||||||
On acknowledgment (or failure, e.g. timeout), the
|
On acknowledgment (or failure, e.g. timeout), the
|
||||||
``_IRQ_GATTS_INDICATE_DONE`` event will be raised.
|
``_IRQ_GATTS_INDICATE_DONE`` event will be raised.
|
||||||
@ -722,7 +702,7 @@ Pairing and bonding
|
|||||||
and ``_IRQ_SET_SECRET`` events.
|
and ``_IRQ_SET_SECRET`` events.
|
||||||
|
|
||||||
**Note:** This is currently only supported when using the NimBLE stack on
|
**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, /)
|
.. method:: BLE.gap_pair(conn_handle, /)
|
||||||
|
|
||||||
|
|||||||
@ -11,9 +11,8 @@ value, a database also supports efficient ordered range scans (retrieval
|
|||||||
of values with the keys in a given range). On the application interface
|
of values with the keys in a given range). On the application interface
|
||||||
side, BTree database work as close a possible to a way standard `dict`
|
side, BTree database work as close a possible to a way standard `dict`
|
||||||
type works, one notable difference is that both keys and values must
|
type works, one notable difference is that both keys and values must
|
||||||
be `bytes`-like objects (so, if you want to store objects of other types, you
|
be `bytes` objects (so, if you want to store objects of other types, you
|
||||||
need to first serialize them to `str` or `bytes` or another type that supports
|
need to serialize them to `bytes` first).
|
||||||
the buffer protocol).
|
|
||||||
|
|
||||||
The module is based on the well-known BerkelyDB library, version 1.xx.
|
The module is based on the well-known BerkelyDB library, version 1.xx.
|
||||||
|
|
||||||
|
|||||||
@ -82,10 +82,6 @@ Functions and types
|
|||||||
In MicroPython, `byteorder` parameter must be positional (this is
|
In MicroPython, `byteorder` parameter must be positional (this is
|
||||||
compatible with CPython).
|
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:: isinstance()
|
||||||
|
|
||||||
.. function:: issubclass()
|
.. function:: issubclass()
|
||||||
|
|||||||
@ -12,15 +12,13 @@ hold/accumulate various objects.
|
|||||||
Classes
|
Classes
|
||||||
-------
|
-------
|
||||||
|
|
||||||
.. class:: deque(iterable, maxlen[, flags])
|
.. function:: deque(iterable, maxlen[, flags])
|
||||||
|
|
||||||
Deques (double-ended queues) are a list-like container that support O(1)
|
Deques (double-ended queues) are a list-like container that support O(1)
|
||||||
appends and pops from either side of the deque. New deques are created
|
appends and pops from either side of the deque. New deques are created
|
||||||
using the following arguments:
|
using the following arguments:
|
||||||
|
|
||||||
- *iterable* is an iterable used to populate the deque when it is
|
- *iterable* must be the empty tuple, and the new deque is created empty.
|
||||||
created. It can be an empty tuple or list to create a deque that
|
|
||||||
is initially empty.
|
|
||||||
|
|
||||||
- *maxlen* must be specified and the deque will be bounded to this
|
- *maxlen* must be specified and the deque will be bounded to this
|
||||||
maximum length. Once the deque is full, any new items added will
|
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.
|
- The optional *flags* can be 1 to check for overflow when adding items.
|
||||||
|
|
||||||
Deque objects support `bool`, `len`, iteration and subscript load and store.
|
As well as supporting `bool` and `len`, deque objects have the following
|
||||||
They also have the following methods:
|
methods:
|
||||||
|
|
||||||
.. method:: deque.append(x)
|
.. method:: deque.append(x)
|
||||||
|
|
||||||
Add *x* to the right side of the deque.
|
Add *x* to the right side of the deque.
|
||||||
Raises ``IndexError`` if overflow checking is enabled and there is
|
Raises IndexError if overflow checking is enabled and there is no more room left.
|
||||||
no more room in the queue.
|
|
||||||
|
|
||||||
.. method:: deque.appendleft(x)
|
|
||||||
|
|
||||||
Add *x* to the left side of the deque.
|
|
||||||
Raises ``IndexError`` if overflow checking is enabled and there is
|
|
||||||
no more room in the queue.
|
|
||||||
|
|
||||||
.. method:: deque.pop()
|
|
||||||
|
|
||||||
Remove and return an item from the right side of the deque.
|
|
||||||
Raises ``IndexError`` if no items are present.
|
|
||||||
|
|
||||||
.. method:: deque.popleft()
|
.. method:: deque.popleft()
|
||||||
|
|
||||||
Remove and return an item from the left side of the deque.
|
Remove and return an item from the left side of the deque.
|
||||||
Raises ``IndexError`` if no items are present.
|
Raises IndexError if no items are present.
|
||||||
|
|
||||||
.. method:: deque.extend(iterable)
|
|
||||||
|
|
||||||
Extend the deque by appending all the items from *iterable* to
|
|
||||||
the right of the deque.
|
|
||||||
Raises ``IndexError`` if overflow checking is enabled and there is
|
|
||||||
no more room in the deque.
|
|
||||||
|
|
||||||
.. function:: namedtuple(name, fields)
|
.. function:: namedtuple(name, fields)
|
||||||
|
|
||||||
@ -78,7 +57,7 @@ Classes
|
|||||||
print(t1.name)
|
print(t1.name)
|
||||||
assert t2.name == t2[1]
|
assert t2.name == t2[1]
|
||||||
|
|
||||||
.. class:: OrderedDict(...)
|
.. function:: OrderedDict(...)
|
||||||
|
|
||||||
``dict`` type subclass which remembers and preserves the order of keys
|
``dict`` type subclass which remembers and preserves the order of keys
|
||||||
added. When ordered dict is iterated over, keys/items are returned in
|
added. When ordered dict is iterated over, keys/items are returned in
|
||||||
|
|||||||
@ -1,182 +0,0 @@
|
|||||||
:mod:`deflate` -- deflate compression & decompression
|
|
||||||
=====================================================
|
|
||||||
|
|
||||||
.. module:: deflate
|
|
||||||
:synopsis: deflate compression & decompression
|
|
||||||
|
|
||||||
This module allows compression and decompression of binary data with the
|
|
||||||
`DEFLATE algorithm <https://en.wikipedia.org/wiki/DEFLATE>`_
|
|
||||||
(commonly used in the zlib library and gzip archiver).
|
|
||||||
|
|
||||||
**Availability:**
|
|
||||||
|
|
||||||
* Added in MicroPython v1.21.
|
|
||||||
|
|
||||||
* Decompression: Enabled via the ``MICROPY_PY_DEFLATE`` build option, on by default
|
|
||||||
on ports with the "extra features" level or higher (which is most boards).
|
|
||||||
|
|
||||||
* Compression: Enabled via the ``MICROPY_PY_DEFLATE_COMPRESS`` build option, on
|
|
||||||
by default on ports with the "full features" level or higher (generally this means
|
|
||||||
you need to build your own firmware to enable this).
|
|
||||||
|
|
||||||
Classes
|
|
||||||
-------
|
|
||||||
|
|
||||||
.. class:: DeflateIO(stream, format=AUTO, wbits=0, close=False, /)
|
|
||||||
|
|
||||||
This class can be used to wrap a *stream* which is any
|
|
||||||
:term:`stream-like <stream>` object such as a file, socket, or stream
|
|
||||||
(including :class:`io.BytesIO`). It is itself a stream and implements the
|
|
||||||
standard read/readinto/write/close methods.
|
|
||||||
|
|
||||||
The *stream* must be a blocking stream. Non-blocking streams are currently
|
|
||||||
not supported.
|
|
||||||
|
|
||||||
The *format* can be set to any of the constants defined below, and defaults
|
|
||||||
to ``AUTO`` which for decompressing will auto-detect gzip or zlib streams,
|
|
||||||
and for compressing it will generate a raw stream.
|
|
||||||
|
|
||||||
The *wbits* parameter sets the base-2 logarithm of the DEFLATE dictionary
|
|
||||||
window size. So for example, setting *wbits* to ``10`` sets the window size
|
|
||||||
to 1024 bytes. Valid values are ``5`` to ``15`` inclusive (corresponding to
|
|
||||||
window sizes of 32 to 32k bytes).
|
|
||||||
|
|
||||||
If *wbits* is set to ``0`` (the default), then for compression a window size
|
|
||||||
of 256 bytes will be used (as if *wbits* was set to 8). For decompression, it
|
|
||||||
depends on the format:
|
|
||||||
|
|
||||||
* ``RAW`` will use 256 bytes (corresponding to *wbits* set to 8).
|
|
||||||
* ``ZLIB`` (or ``AUTO`` with zlib detected) will use the value from the zlib
|
|
||||||
header.
|
|
||||||
* ``GZIP`` (or ``AUTO`` with gzip detected) will use 32 kilobytes
|
|
||||||
(corresponding to *wbits* set to 15).
|
|
||||||
|
|
||||||
See the :ref:`window size <deflate_wbits>` notes below for more information
|
|
||||||
about the window size, zlib, and gzip streams.
|
|
||||||
|
|
||||||
If *close* is set to ``True`` then the underlying stream will be closed
|
|
||||||
automatically when the :class:`deflate.DeflateIO` stream is closed. This is
|
|
||||||
useful if you want to return a :class:`deflate.DeflateIO` stream that wraps
|
|
||||||
another stream and not have the caller need to know about managing the
|
|
||||||
underlying stream.
|
|
||||||
|
|
||||||
If compression is enabled, a given :class:`deflate.DeflateIO` instance
|
|
||||||
supports both reading and writing. For example, a bidirectional stream like
|
|
||||||
a socket can be wrapped, which allows for compression/decompression in both
|
|
||||||
directions.
|
|
||||||
|
|
||||||
Constants
|
|
||||||
---------
|
|
||||||
|
|
||||||
.. data:: deflate.AUTO
|
|
||||||
deflate.RAW
|
|
||||||
deflate.ZLIB
|
|
||||||
deflate.GZIP
|
|
||||||
|
|
||||||
Supported values for the *format* parameter.
|
|
||||||
|
|
||||||
Examples
|
|
||||||
--------
|
|
||||||
|
|
||||||
A typical use case for :class:`deflate.DeflateIO` is to read or write a compressed
|
|
||||||
file from storage:
|
|
||||||
|
|
||||||
.. code:: python
|
|
||||||
|
|
||||||
import deflate
|
|
||||||
|
|
||||||
# Writing a zlib-compressed stream (uses the default window size of 256 bytes).
|
|
||||||
with open("data.gz", "wb") as f:
|
|
||||||
with deflate.DeflateIO(f, deflate.ZLIB) as d:
|
|
||||||
# Use d.write(...) etc
|
|
||||||
|
|
||||||
# Reading a zlib-compressed stream (auto-detect window size).
|
|
||||||
with open("data.z", "rb") as f:
|
|
||||||
with deflate.DeflateIO(f, deflate.ZLIB) as d:
|
|
||||||
# Use d.read(), d.readinto(), etc.
|
|
||||||
|
|
||||||
Because :class:`deflate.DeflateIO` is a stream, it can be used for example
|
|
||||||
with :meth:`json.dump` and :meth:`json.load` (and any other places streams can
|
|
||||||
be used):
|
|
||||||
|
|
||||||
.. code:: python
|
|
||||||
|
|
||||||
import deflate, json
|
|
||||||
|
|
||||||
# Write a dictionary as JSON in gzip format, with a
|
|
||||||
# small (64 byte) window size.
|
|
||||||
config = { ... }
|
|
||||||
with open("config.gz", "wb") as f:
|
|
||||||
with deflate.DeflateIO(f, deflate.GZIP, 6) as f:
|
|
||||||
json.dump(config, f)
|
|
||||||
|
|
||||||
# Read back that dictionary.
|
|
||||||
with open("config.gz", "rb") as f:
|
|
||||||
with deflate.DeflateIO(f, deflate.GZIP, 6) as f:
|
|
||||||
config = json.load(f)
|
|
||||||
|
|
||||||
If your source data is not in a stream format, you can use :class:`io.BytesIO`
|
|
||||||
to turn it into a stream suitable for use with :class:`deflate.DeflateIO`:
|
|
||||||
|
|
||||||
.. code:: python
|
|
||||||
|
|
||||||
import deflate, io
|
|
||||||
|
|
||||||
# Decompress a bytes/bytearray value.
|
|
||||||
compressed_data = get_data_z()
|
|
||||||
with deflate.DeflateIO(io.BytesIO(compressed_data), deflate.ZLIB) as d:
|
|
||||||
decompressed_data = d.read()
|
|
||||||
|
|
||||||
# Compress a bytes/bytearray value.
|
|
||||||
uncompressed_data = get_data()
|
|
||||||
stream = io.BytesIO()
|
|
||||||
with deflate.DeflateIO(stream, deflate.ZLIB) as d:
|
|
||||||
d.write(uncompressed_data)
|
|
||||||
compressed_data = stream.getvalue()
|
|
||||||
|
|
||||||
.. _deflate_wbits:
|
|
||||||
|
|
||||||
Deflate window size
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
The window size limits how far back in the stream the (de)compressor can
|
|
||||||
reference. Increasing the window size will improve compression, but will require
|
|
||||||
more memory and make the compressor slower.
|
|
||||||
|
|
||||||
If an input stream was compressed a given window size, then `DeflateIO`
|
|
||||||
using a smaller window size will fail mid-way during decompression with
|
|
||||||
:exc:`OSError`, but only if a back-reference actually refers back further
|
|
||||||
than the decompressor's window size. This means it may be possible to decompress
|
|
||||||
with a smaller window size. For example, this would trivially be the case if the
|
|
||||||
original uncompressed data is shorter than the window size.
|
|
||||||
|
|
||||||
Decompression
|
|
||||||
~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The zlib format includes a header which specifies the window size that was used
|
|
||||||
to compress the data. This indicates the maximum window size required to
|
|
||||||
decompress this stream. If this header value is less than the specified *wbits*
|
|
||||||
value (or if *wbits* is unset), then the header value will be used.
|
|
||||||
|
|
||||||
The gzip format does not include the window size in the header, and assumes that
|
|
||||||
all gzip compressors (e.g. the ``gzip`` utility, or CPython's implementation of
|
|
||||||
:class:`gzip.GzipFile`) use the maximum window size of 32kiB. For this reason,
|
|
||||||
if the *wbits* parameter is not set, the decompressor will use a 32 kiB window
|
|
||||||
size (corresponding to *wbits* set to 15). This means that to be able to
|
|
||||||
decompress an arbitrary gzip stream, you must have at least this much RAM
|
|
||||||
available. If you control the source data, consider instead using the zlib
|
|
||||||
format with a smaller window size.
|
|
||||||
|
|
||||||
The raw format has no header and therefore does not include any information
|
|
||||||
about the window size. If *wbits* is not set, then it will default to a window
|
|
||||||
size of 256 bytes, which may not be large enough for a given stream. Therefore
|
|
||||||
it is recommended that you should always explicitly set *wbits* if using the raw
|
|
||||||
format.
|
|
||||||
|
|
||||||
Compression
|
|
||||||
~~~~~~~~~~~
|
|
||||||
|
|
||||||
For compression, MicroPython will default to a window size of 256 bytes for all
|
|
||||||
formats. This provides a reasonable amount of compression with minimal memory
|
|
||||||
usage and fast compression time, and will generate output that will work with
|
|
||||||
any decompressor.
|
|
||||||
@ -62,53 +62,6 @@ Functions
|
|||||||
|
|
||||||
.. function:: flash_erase(sector_no)
|
.. function:: flash_erase(sector_no)
|
||||||
|
|
||||||
.. function:: osdebug(uart_no)
|
|
||||||
|
|
||||||
.. note:: This is the ESP8266 form of this function.
|
|
||||||
|
|
||||||
Change the level of OS serial debug log messages. On boot,
|
|
||||||
OS serial debug log messages are disabled.
|
|
||||||
|
|
||||||
``uart_no`` is the number of the UART peripheral which should receive
|
|
||||||
OS-level output, or ``None`` to disable OS serial debug log messages.
|
|
||||||
|
|
||||||
.. function:: osdebug(uart_no, [level])
|
|
||||||
:no-index:
|
|
||||||
|
|
||||||
.. note:: This is the ESP32 form of this function.
|
|
||||||
|
|
||||||
Change the level of OS serial debug log messages. On boot, OS
|
|
||||||
serial debug log messages are limited to Error output only.
|
|
||||||
|
|
||||||
The behaviour of this function depends on the arguments passed to it. The
|
|
||||||
following combinations are supported:
|
|
||||||
|
|
||||||
``osdebug(None)`` restores the default OS debug log message level
|
|
||||||
(``LOG_ERROR``).
|
|
||||||
|
|
||||||
``osdebug(0)`` enables all available OS debug log messages (in the
|
|
||||||
default build configuration this is ``LOG_INFO``).
|
|
||||||
|
|
||||||
``osdebug(0, level)`` sets the OS debug log message level to the
|
|
||||||
specified value. The log levels are defined as constants:
|
|
||||||
|
|
||||||
* ``LOG_NONE`` -- No log output
|
|
||||||
* ``LOG_ERROR`` -- Critical errors, software module can not recover on its own
|
|
||||||
* ``LOG_WARN`` -- Error conditions from which recovery measures have been taken
|
|
||||||
* ``LOG_INFO`` -- Information messages which describe normal flow of events
|
|
||||||
* ``LOG_DEBUG`` -- Extra information which is not necessary for normal use (values, pointers, sizes, etc)
|
|
||||||
* ``LOG_VERBOSE`` -- Bigger chunks of debugging information, or frequent messages
|
|
||||||
which can potentially flood the output
|
|
||||||
|
|
||||||
.. note:: ``LOG_DEBUG`` and ``LOG_VERBOSE`` are not compiled into the
|
|
||||||
MicroPython binary by default, to save size. A custom build with a
|
|
||||||
modified "``sdkconfig``" source file is needed to see any output
|
|
||||||
at these log levels.
|
|
||||||
|
|
||||||
.. note:: Log output on ESP32 is automatically suspended in "Raw REPL" mode,
|
|
||||||
to prevent communications issues. This means OS level logging is never
|
|
||||||
seen when using ``mpremote run`` and similar tools.
|
|
||||||
|
|
||||||
.. function:: set_native_code_location(start, length)
|
.. function:: set_native_code_location(start, length)
|
||||||
|
|
||||||
**Note**: ESP8266 only
|
**Note**: ESP8266 only
|
||||||
|
|||||||
@ -18,11 +18,6 @@ Functions
|
|||||||
Configure whether or not a touch will wake the device from sleep.
|
Configure whether or not a touch will wake the device from sleep.
|
||||||
*wake* should be a boolean value.
|
*wake* should be a boolean value.
|
||||||
|
|
||||||
.. function:: wake_on_ulp(wake)
|
|
||||||
|
|
||||||
Configure whether or not the Ultra-Low-Power co-processor can wake the
|
|
||||||
device from sleep. *wake* should be a boolean value.
|
|
||||||
|
|
||||||
.. function:: wake_on_ext0(pin, level)
|
.. function:: wake_on_ext0(pin, level)
|
||||||
|
|
||||||
Configure how EXT0 wakes the device from sleep. *pin* can be ``None``
|
Configure how EXT0 wakes the device from sleep. *pin* can be ``None``
|
||||||
@ -35,15 +30,14 @@ Functions
|
|||||||
or a tuple/list of valid Pin objects. *level* should be ``esp32.WAKEUP_ALL_LOW``
|
or a tuple/list of valid Pin objects. *level* should be ``esp32.WAKEUP_ALL_LOW``
|
||||||
or ``esp32.WAKEUP_ANY_HIGH``.
|
or ``esp32.WAKEUP_ANY_HIGH``.
|
||||||
|
|
||||||
.. function:: gpio_deep_sleep_hold(enable)
|
|
||||||
|
|
||||||
Configure whether non-RTC GPIO pin configuration is retained during
|
|
||||||
deep-sleep mode for held pads. *enable* should be a boolean value.
|
|
||||||
|
|
||||||
.. function:: raw_temperature()
|
.. function:: raw_temperature()
|
||||||
|
|
||||||
Read the raw value of the internal temperature sensor, returning an integer.
|
Read the raw value of the internal temperature sensor, returning an integer.
|
||||||
|
|
||||||
|
.. function:: hall_sensor()
|
||||||
|
|
||||||
|
Read the raw value of the internal Hall sensor, returning an integer.
|
||||||
|
|
||||||
.. function:: idf_heap_info(capabilities)
|
.. function:: idf_heap_info(capabilities)
|
||||||
|
|
||||||
Returns information about the ESP-IDF heap memory regions. One of them contains
|
Returns information about the ESP-IDF heap memory regions. One of them contains
|
||||||
@ -51,6 +45,8 @@ Functions
|
|||||||
buffers and other data. This data is useful to get a sense of how much memory
|
buffers and other data. This data is useful to get a sense of how much memory
|
||||||
is available to ESP-IDF and the networking stack in particular. It may shed
|
is available to ESP-IDF and the networking stack in particular. It may shed
|
||||||
some light on situations where ESP-IDF operations fail due to allocation failures.
|
some light on situations where ESP-IDF operations fail due to allocation failures.
|
||||||
|
The information returned is *not* useful to troubleshoot Python allocation failures,
|
||||||
|
use `micropython.mem_info()` instead.
|
||||||
|
|
||||||
The capabilities parameter corresponds to ESP-IDF's ``MALLOC_CAP_XXX`` values but the
|
The capabilities parameter corresponds to ESP-IDF's ``MALLOC_CAP_XXX`` values but the
|
||||||
two most useful ones are predefined as `esp32.HEAP_DATA` for data heap regions and
|
two most useful ones are predefined as `esp32.HEAP_DATA` for data heap regions and
|
||||||
@ -66,42 +62,23 @@ Functions
|
|||||||
[(240, 0, 0, 0), (7288, 0, 0, 0), (16648, 4, 4, 4), (79912, 35712, 35512, 35108),
|
[(240, 0, 0, 0), (7288, 0, 0, 0), (16648, 4, 4, 4), (79912, 35712, 35512, 35108),
|
||||||
(15072, 15036, 15036, 15036), (113840, 0, 0, 0)]
|
(15072, 15036, 15036, 15036), (113840, 0, 0, 0)]
|
||||||
|
|
||||||
.. note:: Free IDF heap memory in the `esp32.HEAP_DATA` region is available
|
|
||||||
to be automatically added to the MicroPython heap to prevent a
|
|
||||||
MicroPython allocation from failing. However, the information returned
|
|
||||||
here is otherwise *not* useful to troubleshoot Python allocation
|
|
||||||
failures. :func:`micropython.mem_info()` and :func:`gc.mem_free()` should
|
|
||||||
be used instead:
|
|
||||||
|
|
||||||
The "max new split" value in :func:`micropython.mem_info()` output
|
|
||||||
corresponds to the largest free block of ESP-IDF heap that could be
|
|
||||||
automatically added on demand to the MicroPython heap.
|
|
||||||
|
|
||||||
The result of :func:`gc.mem_free()` is the total of the current "free"
|
|
||||||
and "max new split" values printed by :func:`micropython.mem_info()`.
|
|
||||||
|
|
||||||
|
|
||||||
Flash partitions
|
Flash partitions
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
This class gives access to the partitions in the device's flash memory and includes
|
This class gives access to the partitions in the device's flash memory and includes
|
||||||
methods to enable over-the-air (OTA) updates.
|
methods to enable over-the-air (OTA) updates.
|
||||||
|
|
||||||
.. class:: Partition(id, block_size=4096, /)
|
.. class:: Partition(id)
|
||||||
|
|
||||||
Create an object representing a partition. *id* can be a string which is the label
|
Create an object representing a partition. *id* can be a string which is the label
|
||||||
of the partition to retrieve, or one of the constants: ``BOOT`` or ``RUNNING``.
|
of the partition to retrieve, or one of the constants: ``BOOT`` or ``RUNNING``.
|
||||||
*block_size* specifies the byte size of an individual block.
|
|
||||||
|
|
||||||
.. classmethod:: Partition.find(type=TYPE_APP, subtype=0xff, label=None, block_size=4096)
|
.. classmethod:: Partition.find(type=TYPE_APP, subtype=0xff, label=None)
|
||||||
|
|
||||||
Find a partition specified by *type*, *subtype* and *label*. Returns a
|
Find a partition specified by *type*, *subtype* and *label*. Returns a
|
||||||
(possibly empty) list of Partition objects. Note: ``subtype=0xff`` matches any subtype
|
(possibly empty) list of Partition objects. Note: ``subtype=0xff`` matches any subtype
|
||||||
and ``label=None`` matches any label.
|
and ``label=None`` matches any label.
|
||||||
|
|
||||||
*block_size* specifies the byte size of an individual block used by the returned
|
|
||||||
objects.
|
|
||||||
|
|
||||||
.. method:: Partition.info()
|
.. method:: Partition.info()
|
||||||
|
|
||||||
Returns a 6-tuple ``(type, subtype, addr, size, label, encrypted)``.
|
Returns a 6-tuple ``(type, subtype, addr, size, label, encrypted)``.
|
||||||
@ -114,17 +91,12 @@ methods to enable over-the-air (OTA) updates.
|
|||||||
|
|
||||||
These methods implement the simple and :ref:`extended
|
These methods implement the simple and :ref:`extended
|
||||||
<block-device-interface>` block protocol defined by
|
<block-device-interface>` block protocol defined by
|
||||||
:class:`vfs.AbstractBlockDev`.
|
:class:`os.AbstractBlockDev`.
|
||||||
|
|
||||||
.. method:: Partition.set_boot()
|
.. method:: Partition.set_boot()
|
||||||
|
|
||||||
Sets the partition as the boot partition.
|
Sets the partition as the boot partition.
|
||||||
|
|
||||||
.. note:: Do not enter :func:`deepsleep<machine.deepsleep>` after changing
|
|
||||||
the OTA boot partition, without first performing a hard
|
|
||||||
:func:`reset<machine.reset>` or power cycle. This ensures the bootloader
|
|
||||||
will validate the new image before booting.
|
|
||||||
|
|
||||||
.. method:: Partition.get_next_update()
|
.. method:: Partition.get_next_update()
|
||||||
|
|
||||||
Gets the next update partition after this one, and returns a new Partition object.
|
Gets the next update partition after this one, and returns a new Partition object.
|
||||||
@ -140,7 +112,7 @@ methods to enable over-the-air (OTA) updates.
|
|||||||
and an ``OSError(-261)`` is raised if called on firmware that doesn't have the
|
and an ``OSError(-261)`` is raised if called on firmware that doesn't have the
|
||||||
feature enabled.
|
feature enabled.
|
||||||
It is OK to call ``mark_app_valid_cancel_rollback`` on every boot and it is not
|
It is OK to call ``mark_app_valid_cancel_rollback`` on every boot and it is not
|
||||||
necessary when booting firmware that was loaded using esptool.
|
necessary when booting firmare that was loaded using esptool.
|
||||||
|
|
||||||
Constants
|
Constants
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
@ -193,7 +165,7 @@ numbers specified in ``write_pulses`` are multiplied by the resolution to
|
|||||||
define the pulses.
|
define the pulses.
|
||||||
|
|
||||||
``clock_div`` is an 8-bit divider (0-255) and each pulse can be defined by
|
``clock_div`` is an 8-bit divider (0-255) and each pulse can be defined by
|
||||||
multiplying the resolution by a 15-bit (1-``PULSE_MAX``) number. There are eight
|
multiplying the resolution by a 15-bit (0-32,768) number. There are eight
|
||||||
channels (0-7) and each can have a different clock divider.
|
channels (0-7) and each can have a different clock divider.
|
||||||
|
|
||||||
So, in the example above, the 80MHz clock is divided by 8. Thus the
|
So, in the example above, the 80MHz clock is divided by 8. Thus the
|
||||||
@ -226,7 +198,7 @@ For more details see Espressif's `ESP-IDF RMT documentation.
|
|||||||
``100``) and the output level to apply the carrier to (a boolean as per
|
``100``) and the output level to apply the carrier to (a boolean as per
|
||||||
*idle_level*).
|
*idle_level*).
|
||||||
|
|
||||||
.. classmethod:: RMT.source_freq()
|
.. method:: RMT.source_freq()
|
||||||
|
|
||||||
Returns the source clock frequency. Currently the source clock is not
|
Returns the source clock frequency. Currently the source clock is not
|
||||||
configurable so this will always return 80MHz.
|
configurable so this will always return 80MHz.
|
||||||
@ -264,10 +236,10 @@ For more details see Espressif's `ESP-IDF RMT documentation.
|
|||||||
**Mode 3:** *duration* and *data* are lists or tuples of equal length,
|
**Mode 3:** *duration* and *data* are lists or tuples of equal length,
|
||||||
specifying individual durations and the output level for each.
|
specifying individual durations and the output level for each.
|
||||||
|
|
||||||
Durations are in integer units of the channel resolution (as
|
Durations are in integer units of the channel resolution (as described
|
||||||
described above), between 1 and ``PULSE_MAX`` units. Output levels
|
above), between 1 and 32767 units. Output levels are any value that can
|
||||||
are any value that can be converted to a boolean, with ``True``
|
be converted to a boolean, with ``True`` representing high voltage and
|
||||||
representing high voltage and ``False`` representing low.
|
``False`` representing low.
|
||||||
|
|
||||||
If transmission of an earlier sequence is in progress then this method will
|
If transmission of an earlier sequence is in progress then this method will
|
||||||
block until that transmission is complete before beginning the new sequence.
|
block until that transmission is complete before beginning the new sequence.
|
||||||
@ -278,36 +250,10 @@ For more details see Espressif's `ESP-IDF RMT documentation.
|
|||||||
new sequence of pulses. Looping sequences longer than 126 pulses is not
|
new sequence of pulses. Looping sequences longer than 126 pulses is not
|
||||||
supported by the hardware.
|
supported by the hardware.
|
||||||
|
|
||||||
.. staticmethod:: RMT.bitstream_channel([value])
|
|
||||||
|
|
||||||
Select which RMT channel is used by the `machine.bitstream` implementation.
|
|
||||||
*value* can be ``None`` or a valid RMT channel number. The default RMT
|
|
||||||
channel is the highest numbered one.
|
|
||||||
|
|
||||||
Passing in ``None`` disables the use of RMT and instead selects a bit-banging
|
|
||||||
implementation for `machine.bitstream`.
|
|
||||||
|
|
||||||
Passing in no argument will not change the channel. This function returns
|
|
||||||
the current channel number.
|
|
||||||
|
|
||||||
Constants
|
|
||||||
---------
|
|
||||||
|
|
||||||
.. data:: RMT.PULSE_MAX
|
|
||||||
|
|
||||||
Maximum integer that can be set for a pulse duration.
|
|
||||||
|
|
||||||
Ultra-Low-Power co-processor
|
Ultra-Low-Power co-processor
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
This class gives access to the Ultra Low Power (ULP) co-processor on the ESP32,
|
|
||||||
ESP32-S2 and ESP32-S3 chips.
|
|
||||||
|
|
||||||
.. warning::
|
|
||||||
|
|
||||||
This class does not provide access to the RISCV ULP co-processor available
|
|
||||||
on the ESP32-S2 and ESP32-S3 chips.
|
|
||||||
|
|
||||||
.. class:: ULP()
|
.. class:: ULP()
|
||||||
|
|
||||||
This class provides access to the Ultra-Low-Power co-processor.
|
This class provides access to the Ultra-Low-Power co-processor.
|
||||||
|
|||||||
@ -1,936 +0,0 @@
|
|||||||
:mod:`espnow` --- support for the ESP-NOW wireless protocol
|
|
||||||
===========================================================
|
|
||||||
|
|
||||||
.. module:: espnow
|
|
||||||
:synopsis: ESP-NOW wireless protocol support
|
|
||||||
|
|
||||||
This module provides an interface to the `ESP-NOW <https://www.espressif.com/
|
|
||||||
en/products/software/esp-now/overview>`_ protocol provided by Espressif on
|
|
||||||
ESP32 and ESP8266 devices (`API docs <https://docs.espressif.com/
|
|
||||||
projects/esp-idf/en/latest/api-reference/network/esp_now.html>`_).
|
|
||||||
|
|
||||||
Table of Contents:
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- `Introduction`_
|
|
||||||
- `Configuration`_
|
|
||||||
- `Sending and Receiving Data`_
|
|
||||||
- `Peer Management`_
|
|
||||||
- `Callback Methods`_
|
|
||||||
- `Exceptions`_
|
|
||||||
- `Constants`_
|
|
||||||
- `Wifi Signal Strength (RSSI) - (ESP32 Only)`_
|
|
||||||
- `Supporting asyncio`_
|
|
||||||
- `Broadcast and Multicast`_
|
|
||||||
- `ESPNow and Wifi Operation`_
|
|
||||||
- `ESPNow and Sleep Modes`_
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
------------
|
|
||||||
|
|
||||||
ESP-NOW is a connection-less wireless communication protocol supporting:
|
|
||||||
|
|
||||||
- Direct communication between up to 20 registered peers:
|
|
||||||
|
|
||||||
- Without the need for a wireless access point (AP),
|
|
||||||
|
|
||||||
- Encrypted and unencrypted communication (up to 6 encrypted peers),
|
|
||||||
|
|
||||||
- Message sizes up to 250 bytes,
|
|
||||||
|
|
||||||
- Can operate alongside Wifi operation (:doc:`network.WLAN<network.WLAN>`) on
|
|
||||||
ESP32 and ESP8266 devices.
|
|
||||||
|
|
||||||
It is especially useful for small IoT networks, latency sensitive or power
|
|
||||||
sensitive applications (such as battery operated devices) and for long-range
|
|
||||||
communication between devices (hundreds of metres).
|
|
||||||
|
|
||||||
This module also supports tracking the Wifi signal strength (RSSI) of peer
|
|
||||||
devices.
|
|
||||||
|
|
||||||
A simple example would be:
|
|
||||||
|
|
||||||
**Sender:** ::
|
|
||||||
|
|
||||||
import network
|
|
||||||
import espnow
|
|
||||||
|
|
||||||
# A WLAN interface must be active to send()/recv()
|
|
||||||
sta = network.WLAN(network.STA_IF) # Or network.AP_IF
|
|
||||||
sta.active(True)
|
|
||||||
sta.disconnect() # For ESP8266
|
|
||||||
|
|
||||||
e = espnow.ESPNow()
|
|
||||||
e.active(True)
|
|
||||||
peer = b'\xbb\xbb\xbb\xbb\xbb\xbb' # MAC address of peer's wifi interface
|
|
||||||
e.add_peer(peer) # Must add_peer() before send()
|
|
||||||
|
|
||||||
e.send(peer, "Starting...")
|
|
||||||
for i in range(100):
|
|
||||||
e.send(peer, str(i)*20, True)
|
|
||||||
e.send(peer, b'end')
|
|
||||||
|
|
||||||
**Receiver:** ::
|
|
||||||
|
|
||||||
import network
|
|
||||||
import espnow
|
|
||||||
|
|
||||||
# A WLAN interface must be active to send()/recv()
|
|
||||||
sta = network.WLAN(network.STA_IF)
|
|
||||||
sta.active(True)
|
|
||||||
sta.disconnect() # Because ESP8266 auto-connects to last Access Point
|
|
||||||
|
|
||||||
e = espnow.ESPNow()
|
|
||||||
e.active(True)
|
|
||||||
|
|
||||||
while True:
|
|
||||||
host, msg = e.recv()
|
|
||||||
if msg: # msg == None if timeout in recv()
|
|
||||||
print(host, msg)
|
|
||||||
if msg == b'end':
|
|
||||||
break
|
|
||||||
|
|
||||||
class ESPNow
|
|
||||||
------------
|
|
||||||
|
|
||||||
Constructor
|
|
||||||
-----------
|
|
||||||
|
|
||||||
.. class:: ESPNow()
|
|
||||||
|
|
||||||
Returns the singleton ESPNow object. As this is a singleton, all calls to
|
|
||||||
`espnow.ESPNow()` return a reference to the same object.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
Some methods are available only on the ESP32 due to code size
|
|
||||||
restrictions on the ESP8266 and differences in the Espressif API.
|
|
||||||
|
|
||||||
Configuration
|
|
||||||
-------------
|
|
||||||
|
|
||||||
.. method:: ESPNow.active([flag])
|
|
||||||
|
|
||||||
Initialise or de-initialise the ESP-NOW communication protocol depending on
|
|
||||||
the value of the ``flag`` optional argument.
|
|
||||||
|
|
||||||
.. data:: Arguments:
|
|
||||||
|
|
||||||
- *flag*: Any python value which can be converted to a boolean type.
|
|
||||||
|
|
||||||
- ``True``: Prepare the software and hardware for use of the ESP-NOW
|
|
||||||
communication protocol, including:
|
|
||||||
|
|
||||||
- initialise the ESPNow data structures,
|
|
||||||
- allocate the recv data buffer,
|
|
||||||
- invoke esp_now_init() and
|
|
||||||
- register the send and recv callbacks.
|
|
||||||
|
|
||||||
- ``False``: De-initialise the Espressif ESP-NOW software stack
|
|
||||||
(esp_now_deinit()), disable callbacks, deallocate the recv
|
|
||||||
data buffer and deregister all peers.
|
|
||||||
|
|
||||||
If *flag* is not provided, return the current status of the ESPNow
|
|
||||||
interface.
|
|
||||||
|
|
||||||
.. data:: Returns:
|
|
||||||
|
|
||||||
``True`` if interface is currently *active*, else ``False``.
|
|
||||||
|
|
||||||
.. method:: ESPNow.config(param=value, ...)
|
|
||||||
ESPNow.config('param') (ESP32 only)
|
|
||||||
|
|
||||||
Set or get configuration values of the ESPNow interface. To set values, use
|
|
||||||
the keyword syntax, and one or more parameters can be set at a time. To get
|
|
||||||
a value the parameter name should be quoted as a string, and just one
|
|
||||||
parameter is queried at a time.
|
|
||||||
|
|
||||||
**Note:** *Getting* parameters is not supported on the ESP8266.
|
|
||||||
|
|
||||||
.. data:: Options:
|
|
||||||
|
|
||||||
*rxbuf*: (default=526) Get/set the size in bytes of the internal
|
|
||||||
buffer used to store incoming ESPNow packet data. The default size is
|
|
||||||
selected to fit two max-sized ESPNow packets (250 bytes) with associated
|
|
||||||
mac_address (6 bytes), a message byte count (1 byte) and RSSI data plus
|
|
||||||
buffer overhead. Increase this if you expect to receive a lot of large
|
|
||||||
packets or expect bursty incoming traffic.
|
|
||||||
|
|
||||||
**Note:** The recv buffer is allocated by `ESPNow.active()`. Changing
|
|
||||||
this value will have no effect until the next call of
|
|
||||||
`ESPNow.active(True)<ESPNow.active()>`.
|
|
||||||
|
|
||||||
*timeout_ms*: (default=300,000) Default timeout (in milliseconds)
|
|
||||||
for receiving ESPNow messages. If *timeout_ms* is less than zero, then
|
|
||||||
wait forever. The timeout can also be provided as arg to
|
|
||||||
`recv()`/`irecv()`/`recvinto()`.
|
|
||||||
|
|
||||||
*rate*: (ESP32 only, IDF>=4.3.0 only) Set the transmission speed for
|
|
||||||
ESPNow packets. Must be set to a number from the allowed numeric values
|
|
||||||
in `enum wifi_phy_rate_t
|
|
||||||
<https://docs.espressif.com/projects/esp-idf/en/v4.4.1/esp32/
|
|
||||||
api-reference/network/esp_wifi.html#_CPPv415wifi_phy_rate_t>`_.
|
|
||||||
|
|
||||||
.. data:: Returns:
|
|
||||||
|
|
||||||
``None`` or the value of the parameter being queried.
|
|
||||||
|
|
||||||
.. data:: Raises:
|
|
||||||
|
|
||||||
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised.
|
|
||||||
- ``ValueError()`` on invalid configuration options or values.
|
|
||||||
|
|
||||||
Sending and Receiving Data
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
A wifi interface (``network.STA_IF`` or ``network.AP_IF``) must be
|
|
||||||
`active()<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.STA_IF)
|
|
||||||
sta.active(True)
|
|
||||||
sta.disconnect() # For ESP8266
|
|
||||||
|
|
||||||
**Note:** The ESP8266 has a *feature* that causes it to automatically reconnect
|
|
||||||
to the last wifi Access Point when set `active(True)<network.WLAN.active>` (even
|
|
||||||
after reboot/reset). This reduces the reliability of receiving ESP-NOW messages
|
|
||||||
(see `ESPNow and Wifi Operation`_). You can avoid this by calling
|
|
||||||
`disconnect()<network.WLAN.disconnect>` after
|
|
||||||
`active(True)<network.WLAN.active>`.
|
|
||||||
|
|
||||||
.. method:: ESPNow.send(mac, msg[, sync])
|
|
||||||
ESPNow.send(msg) (ESP32 only)
|
|
||||||
|
|
||||||
Send the data contained in ``msg`` to the peer with given network ``mac``
|
|
||||||
address. In the second form, ``mac=None`` and ``sync=True``. The peer must
|
|
||||||
be registered with `ESPNow.add_peer()<ESPNow.add_peer()>` before the
|
|
||||||
message can be sent.
|
|
||||||
|
|
||||||
.. data:: Arguments:
|
|
||||||
|
|
||||||
- *mac*: byte string exactly ``espnow.ADDR_LEN`` (6 bytes) long or
|
|
||||||
``None``. If *mac* is ``None`` (ESP32 only) the message will be sent
|
|
||||||
to all registered peers, except any broadcast or multicast MAC
|
|
||||||
addresses.
|
|
||||||
|
|
||||||
- *msg*: string or byte-string up to ``espnow.MAX_DATA_LEN`` (250)
|
|
||||||
bytes long.
|
|
||||||
|
|
||||||
- *sync*:
|
|
||||||
|
|
||||||
- ``True``: (default) send ``msg`` to the peer(s) and wait for a
|
|
||||||
response (or not).
|
|
||||||
|
|
||||||
- ``False`` send ``msg`` and return immediately. Responses from the
|
|
||||||
peers will be discarded.
|
|
||||||
|
|
||||||
.. data:: Returns:
|
|
||||||
|
|
||||||
``True`` if ``sync=False`` or if ``sync=True`` and *all* peers respond,
|
|
||||||
else ``False``.
|
|
||||||
|
|
||||||
.. data:: Raises:
|
|
||||||
|
|
||||||
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised.
|
|
||||||
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_FOUND")`` if peer is not registered.
|
|
||||||
- ``OSError(num, "ESP_ERR_ESPNOW_IF")`` the wifi interface is not
|
|
||||||
`active()<network.WLAN.active>`.
|
|
||||||
- ``OSError(num, "ESP_ERR_ESPNOW_NO_MEM")`` internal ESP-NOW buffers are
|
|
||||||
full.
|
|
||||||
- ``ValueError()`` on invalid values for the parameters.
|
|
||||||
|
|
||||||
**Note**: A peer will respond with success if its wifi interface is
|
|
||||||
`active()<network.WLAN.active>` and set to the same channel as the sender,
|
|
||||||
regardless of whether it has initialised it's ESP-NOW system or is
|
|
||||||
actively listening for ESP-NOW traffic (see the Espressif ESP-NOW docs).
|
|
||||||
|
|
||||||
.. method:: ESPNow.recv([timeout_ms])
|
|
||||||
|
|
||||||
Wait for an incoming message and return the ``mac`` address of the peer and
|
|
||||||
the message. **Note**: It is **not** necessary to register a peer (using
|
|
||||||
`add_peer()<ESPNow.add_peer()>`) to receive a message from that peer.
|
|
||||||
|
|
||||||
.. data:: Arguments:
|
|
||||||
|
|
||||||
- *timeout_ms*: (Optional): May have the following values.
|
|
||||||
|
|
||||||
- ``0``: No timeout. Return immediately if no data is available;
|
|
||||||
- ``> 0``: Specify a timeout value in milliseconds;
|
|
||||||
- ``< 0``: Do not timeout, ie. wait forever for new messages; or
|
|
||||||
- ``None`` (or not provided): Use the default timeout value set with
|
|
||||||
`ESPNow.config()`.
|
|
||||||
|
|
||||||
.. data:: Returns:
|
|
||||||
|
|
||||||
- ``(None, None)`` if timeout is reached before a message is received, or
|
|
||||||
|
|
||||||
- ``[mac, msg]``: where:
|
|
||||||
|
|
||||||
- ``mac`` is a bytestring containing the address of the device which
|
|
||||||
sent the message, and
|
|
||||||
- ``msg`` is a bytestring containing the message.
|
|
||||||
|
|
||||||
.. data:: Raises:
|
|
||||||
|
|
||||||
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised.
|
|
||||||
- ``OSError(num, "ESP_ERR_ESPNOW_IF")`` if the wifi interface is not
|
|
||||||
`active()<network.WLAN.active>`.
|
|
||||||
- ``ValueError()`` on invalid *timeout_ms* values.
|
|
||||||
|
|
||||||
`ESPNow.recv()` will allocate new storage for the returned list and the
|
|
||||||
``peer`` and ``msg`` bytestrings. This can lead to memory fragmentation if
|
|
||||||
the data rate is high. See `ESPNow.irecv()` for a memory-friendly
|
|
||||||
alternative.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: ESPNow.irecv([timeout_ms])
|
|
||||||
|
|
||||||
Works like `ESPNow.recv()` but will reuse internal bytearrays to store the
|
|
||||||
return values: ``[mac, msg]``, so that no new memory is allocated on each
|
|
||||||
call.
|
|
||||||
|
|
||||||
.. data:: Arguments:
|
|
||||||
|
|
||||||
*timeout_ms*: (Optional) Timeout in milliseconds (see `ESPNow.recv()`).
|
|
||||||
|
|
||||||
.. data:: Returns:
|
|
||||||
|
|
||||||
- As for `ESPNow.recv()`, except that ``msg`` is a bytearray, instead of
|
|
||||||
a bytestring. On the ESP8266, ``mac`` will also be a bytearray.
|
|
||||||
|
|
||||||
.. data:: Raises:
|
|
||||||
|
|
||||||
- See `ESPNow.recv()`.
|
|
||||||
|
|
||||||
**Note:** You may also read messages by iterating over the ESPNow object,
|
|
||||||
which will use the `irecv()` method for alloc-free reads, eg: ::
|
|
||||||
|
|
||||||
import espnow
|
|
||||||
e = espnow.ESPNow(); e.active(True)
|
|
||||||
for mac, msg in e:
|
|
||||||
print(mac, msg)
|
|
||||||
if mac is None: # mac, msg will equal (None, None) on timeout
|
|
||||||
break
|
|
||||||
|
|
||||||
.. method:: ESPNow.recvinto(data[, timeout_ms])
|
|
||||||
|
|
||||||
Wait for an incoming message and return the length of the message in bytes.
|
|
||||||
This is the low-level method used by both `recv()<ESPNow.recv()>` and
|
|
||||||
`irecv()` to read messages.
|
|
||||||
|
|
||||||
.. data:: Arguments:
|
|
||||||
|
|
||||||
*data*: A list of at least two elements, ``[peer, msg]``. ``msg`` must
|
|
||||||
be a bytearray large enough to hold the message (250 bytes). On the
|
|
||||||
ESP8266, ``peer`` should be a bytearray of 6 bytes. The MAC address of
|
|
||||||
the sender and the message will be stored in these bytearrays (see Note
|
|
||||||
on ESP32 below).
|
|
||||||
|
|
||||||
*timeout_ms*: (Optional) Timeout in milliseconds (see `ESPNow.recv()`).
|
|
||||||
|
|
||||||
.. data:: Returns:
|
|
||||||
|
|
||||||
- Length of message in bytes or 0 if *timeout_ms* is reached before a
|
|
||||||
message is received.
|
|
||||||
|
|
||||||
.. data:: Raises:
|
|
||||||
|
|
||||||
- See `ESPNow.recv()`.
|
|
||||||
|
|
||||||
**Note:** On the ESP32:
|
|
||||||
|
|
||||||
- It is unnecessary to provide a bytearray in the first element of the
|
|
||||||
``data`` list because it will be replaced by a reference to a unique
|
|
||||||
``peer`` address in the **peer device table** (see `ESPNow.peers_table`).
|
|
||||||
- If the list is at least 4 elements long, the rssi and timestamp values
|
|
||||||
will be saved as the 3rd and 4th elements.
|
|
||||||
|
|
||||||
.. method:: ESPNow.any()
|
|
||||||
|
|
||||||
Check if data is available to be read with `ESPNow.recv()`.
|
|
||||||
|
|
||||||
For more sophisticated querying of available characters use `select.poll()`::
|
|
||||||
|
|
||||||
import select
|
|
||||||
import espnow
|
|
||||||
|
|
||||||
e = espnow.ESPNow()
|
|
||||||
poll = select.poll()
|
|
||||||
poll.register(e, select.POLLIN)
|
|
||||||
poll.poll(timeout)
|
|
||||||
|
|
||||||
.. data:: Returns:
|
|
||||||
|
|
||||||
``True`` if data is available to be read, else ``False``.
|
|
||||||
|
|
||||||
.. method:: ESPNow.stats() (ESP32 only)
|
|
||||||
|
|
||||||
.. data:: Returns:
|
|
||||||
|
|
||||||
A 5-tuple containing the number of packets sent/received/lost:
|
|
||||||
|
|
||||||
``(tx_pkts, tx_responses, tx_failures, rx_packets, rx_dropped_packets)``
|
|
||||||
|
|
||||||
Incoming packets are *dropped* when the recv buffers are full. To reduce
|
|
||||||
packet loss, increase the ``rxbuf`` config parameters and ensure you are
|
|
||||||
reading messages as quickly as possible.
|
|
||||||
|
|
||||||
**Note**: Dropped packets will still be acknowledged to the sender as
|
|
||||||
received.
|
|
||||||
|
|
||||||
Peer Management
|
|
||||||
---------------
|
|
||||||
|
|
||||||
On ESP32 devices, the Espressif ESP-NOW software requires that other devices
|
|
||||||
(peers) must be *registered* using `add_peer()` before we can
|
|
||||||
`send()<ESPNow.send()>` them messages (this is *not* enforced on ESP8266
|
|
||||||
devices). It is **not** necessary to register a peer to receive an
|
|
||||||
un-encrypted message from that peer.
|
|
||||||
|
|
||||||
**Encrypted messages**: To receive an *encrypted* message, the receiving device
|
|
||||||
must first register the sender and use the same encryption keys as the sender
|
|
||||||
(PMK and LMK) (see `set_pmk()` and `add_peer()`.
|
|
||||||
|
|
||||||
.. method:: ESPNow.set_pmk(pmk)
|
|
||||||
|
|
||||||
Set the Primary Master Key (PMK) which is used to encrypt the Local Master
|
|
||||||
Keys (LMK) for encrypting messages. If this is not set, a default PMK is
|
|
||||||
used by the underlying Espressif ESP-NOW software stack.
|
|
||||||
|
|
||||||
**Note:** messages will only be encrypted if *lmk* is also set in
|
|
||||||
`ESPNow.add_peer()` (see `Security
|
|
||||||
<https://docs.espressif.com/projects/esp-idf/en/latest/
|
|
||||||
esp32/api-reference/network/esp_now.html#security>`_ in the Espressif API
|
|
||||||
docs).
|
|
||||||
|
|
||||||
.. data:: Arguments:
|
|
||||||
|
|
||||||
*pmk*: Must be a byte string, bytearray or string of length
|
|
||||||
`espnow.KEY_LEN` (16 bytes).
|
|
||||||
|
|
||||||
.. data:: Returns:
|
|
||||||
|
|
||||||
``None``
|
|
||||||
|
|
||||||
.. data:: Raises:
|
|
||||||
|
|
||||||
``ValueError()`` on invalid *pmk* values.
|
|
||||||
|
|
||||||
.. method:: ESPNow.add_peer(mac, [lmk], [channel], [ifidx], [encrypt])
|
|
||||||
ESPNow.add_peer(mac, param=value, ...) (ESP32 only)
|
|
||||||
|
|
||||||
Add/register the provided *mac* address as a peer. Additional parameters may
|
|
||||||
also be specified as positional or keyword arguments (any parameter set to
|
|
||||||
``None`` will be set to it's default value):
|
|
||||||
|
|
||||||
.. data:: Arguments:
|
|
||||||
|
|
||||||
- *mac*: The MAC address of the peer (as a 6-byte byte-string).
|
|
||||||
|
|
||||||
- *lmk*: The Local Master Key (LMK) key used to encrypt data
|
|
||||||
transfers with this peer (unless the *encrypt* parameter is set to
|
|
||||||
``False``). Must be:
|
|
||||||
|
|
||||||
- a byte-string or bytearray or string of length ``espnow.KEY_LEN``
|
|
||||||
(16 bytes), or
|
|
||||||
|
|
||||||
- any non ``True`` python value (default= ``b''``), signifying an
|
|
||||||
*empty* key which will disable encryption.
|
|
||||||
|
|
||||||
- *channel*: The wifi channel (2.4GHz) to communicate with this peer.
|
|
||||||
Must be an integer from 0 to 14. If channel is set to 0 the current
|
|
||||||
channel of the wifi device will be used. (default=0)
|
|
||||||
|
|
||||||
- *ifidx*: (ESP32 only) Index of the wifi interface which will be
|
|
||||||
used to send data to this peer. Must be an integer set to
|
|
||||||
``network.STA_IF`` (=0) or ``network.AP_IF`` (=1).
|
|
||||||
(default=0/``network.STA_IF``). See `ESPNow and Wifi Operation`_
|
|
||||||
below for more information.
|
|
||||||
|
|
||||||
- *encrypt*: (ESP32 only) If set to ``True`` data exchanged with
|
|
||||||
this peer will be encrypted with the PMK and LMK. (default =
|
|
||||||
``True`` if *lmk* is set to a valid key, else ``False``)
|
|
||||||
|
|
||||||
**ESP8266**: Keyword args may not be used on the ESP8266.
|
|
||||||
|
|
||||||
**Note:** The maximum number of peers which may be registered is 20
|
|
||||||
(`espnow.MAX_TOTAL_PEER_NUM`), with a maximum of 6
|
|
||||||
(`espnow.MAX_ENCRYPT_PEER_NUM`) of those peers with encryption enabled
|
|
||||||
(see `ESP_NOW_MAX_ENCRYPT_PEER_NUM <https://docs.espressif.com/
|
|
||||||
projects/esp-idf/en/latest/esp32/api-reference/network/
|
|
||||||
esp_now.html#c.ESP_NOW_MAX_ENCRYPT_PEER_NUM>`_ in the Espressif API
|
|
||||||
docs).
|
|
||||||
|
|
||||||
.. data:: Raises:
|
|
||||||
|
|
||||||
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised.
|
|
||||||
- ``OSError(num, "ESP_ERR_ESPNOW_EXIST")`` if *mac* is already
|
|
||||||
registered.
|
|
||||||
- ``OSError(num, "ESP_ERR_ESPNOW_FULL")`` if too many peers are
|
|
||||||
already registered.
|
|
||||||
- ``ValueError()`` on invalid keyword args or values.
|
|
||||||
|
|
||||||
.. method:: ESPNow.del_peer(mac)
|
|
||||||
|
|
||||||
Deregister the peer associated with the provided *mac* address.
|
|
||||||
|
|
||||||
.. data:: Returns:
|
|
||||||
|
|
||||||
``None``
|
|
||||||
|
|
||||||
.. data:: Raises:
|
|
||||||
|
|
||||||
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised.
|
|
||||||
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_FOUND")`` if *mac* is not
|
|
||||||
registered.
|
|
||||||
- ``ValueError()`` on invalid *mac* values.
|
|
||||||
|
|
||||||
.. method:: ESPNow.get_peer(mac) (ESP32 only)
|
|
||||||
|
|
||||||
Return information on a registered peer.
|
|
||||||
|
|
||||||
.. data:: Returns:
|
|
||||||
|
|
||||||
``(mac, lmk, channel, ifidx, encrypt)``: a tuple of the "peer
|
|
||||||
info" associated with the given *mac* address.
|
|
||||||
|
|
||||||
.. data:: Raises:
|
|
||||||
|
|
||||||
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised.
|
|
||||||
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_FOUND")`` if *mac* is not
|
|
||||||
registered.
|
|
||||||
- ``ValueError()`` on invalid *mac* values.
|
|
||||||
|
|
||||||
.. method:: ESPNow.peer_count() (ESP32 only)
|
|
||||||
|
|
||||||
Return the number of registered peers:
|
|
||||||
|
|
||||||
- ``(peer_num, encrypt_num)``: where
|
|
||||||
|
|
||||||
- ``peer_num`` is the number of peers which are registered, and
|
|
||||||
- ``encrypt_num`` is the number of encrypted peers.
|
|
||||||
|
|
||||||
.. method:: ESPNow.get_peers() (ESP32 only)
|
|
||||||
|
|
||||||
Return the "peer info" parameters for all the registered peers (as a tuple
|
|
||||||
of tuples).
|
|
||||||
|
|
||||||
.. method:: ESPNow.mod_peer(mac, lmk, [channel], [ifidx], [encrypt]) (ESP32 only)
|
|
||||||
ESPNow.mod_peer(mac, 'param'=value, ...) (ESP32 only)
|
|
||||||
|
|
||||||
Modify the parameters of the peer associated with the provided *mac*
|
|
||||||
address. Parameters may be provided as positional or keyword arguments
|
|
||||||
(see `ESPNow.add_peer()`). Any parameter that is not set (or set to
|
|
||||||
``None``) will retain the existing value for that parameter.
|
|
||||||
|
|
||||||
Callback Methods
|
|
||||||
----------------
|
|
||||||
|
|
||||||
.. method:: ESPNow.irq(callback) (ESP32 only)
|
|
||||||
|
|
||||||
Set a callback function to be called *as soon as possible* after a message has
|
|
||||||
been received from another ESPNow device. The callback function will be called
|
|
||||||
with the `ESPNow` instance object as an argument. For more reliable operation,
|
|
||||||
it is recommended to read out as many messages as are available when the
|
|
||||||
callback is invoked and to set the read timeout to zero, eg: ::
|
|
||||||
|
|
||||||
def recv_cb(e):
|
|
||||||
while True: # Read out all messages waiting in the buffer
|
|
||||||
mac, msg = e.irecv(0) # Don't wait if no messages left
|
|
||||||
if mac is None:
|
|
||||||
return
|
|
||||||
print(mac, msg)
|
|
||||||
e.irq(recv_cb)
|
|
||||||
|
|
||||||
The `irq()<ESPNow.irq()>` callback method is an alternative method for
|
|
||||||
processing incoming messages, especially if the data rate is moderate
|
|
||||||
and the device is *not too busy* but there are some caveats:
|
|
||||||
|
|
||||||
- The scheduler stack *can* overflow and callbacks will be missed if
|
|
||||||
packets are arriving at a sufficient rate or if other MicroPython components
|
|
||||||
(eg, bluetooth, machine.Pin.irq(), machine.timer, i2s, ...) are exercising
|
|
||||||
the scheduler stack. This method may be less reliable for dealing with
|
|
||||||
bursts of messages, or high throughput or on a device which is busy dealing
|
|
||||||
with other hardware operations.
|
|
||||||
|
|
||||||
- For more information on *scheduled* function callbacks see:
|
|
||||||
`micropython.schedule()<micropython.schedule>`.
|
|
||||||
|
|
||||||
Constants
|
|
||||||
---------
|
|
||||||
|
|
||||||
.. data:: espnow.MAX_DATA_LEN(=250)
|
|
||||||
espnow.KEY_LEN(=16)
|
|
||||||
espnow.ADDR_LEN(=6)
|
|
||||||
espnow.MAX_TOTAL_PEER_NUM(=20)
|
|
||||||
espnow.MAX_ENCRYPT_PEER_NUM(=6)
|
|
||||||
|
|
||||||
Exceptions
|
|
||||||
----------
|
|
||||||
|
|
||||||
If the underlying Espressif ESP-NOW software stack returns an error code,
|
|
||||||
the MicroPython espnow module will raise an ``OSError(errnum, errstring)``
|
|
||||||
exception where ``errstring`` is set to the name of one of the error codes
|
|
||||||
identified in the
|
|
||||||
`Espressif ESP-NOW docs
|
|
||||||
<https://docs.espressif.com/projects/esp-idf/en/latest/
|
|
||||||
api-reference/network/esp_now.html#api-reference>`_. For example::
|
|
||||||
|
|
||||||
try:
|
|
||||||
e.send(peer, 'Hello')
|
|
||||||
except OSError as err:
|
|
||||||
if len(err.args) < 2:
|
|
||||||
raise err
|
|
||||||
if err.args[1] == 'ESP_ERR_ESPNOW_NOT_INIT':
|
|
||||||
e.active(True)
|
|
||||||
elif err.args[1] == 'ESP_ERR_ESPNOW_NOT_FOUND':
|
|
||||||
e.add_peer(peer)
|
|
||||||
elif err.args[1] == 'ESP_ERR_ESPNOW_IF':
|
|
||||||
network.WLAN(network.STA_IF).active(True)
|
|
||||||
else:
|
|
||||||
raise err
|
|
||||||
|
|
||||||
Wifi Signal Strength (RSSI) - (ESP32 only)
|
|
||||||
------------------------------------------
|
|
||||||
|
|
||||||
The ESPNow object maintains a **peer device table** which contains the signal
|
|
||||||
strength and timestamp of the last received message from all hosts. The **peer
|
|
||||||
device table** can be accessed using `ESPNow.peers_table` and can be used to
|
|
||||||
track device proximity and identify *nearest neighbours* in a network of peer
|
|
||||||
devices. This feature is **not** available on ESP8266 devices.
|
|
||||||
|
|
||||||
.. data:: ESPNow.peers_table
|
|
||||||
|
|
||||||
A reference to the **peer device table**: a dict of known peer devices
|
|
||||||
and rssi values::
|
|
||||||
|
|
||||||
{peer: [rssi, time_ms], ...}
|
|
||||||
|
|
||||||
where:
|
|
||||||
|
|
||||||
- ``peer`` is the peer MAC address (as `bytes`);
|
|
||||||
- ``rssi`` is the wifi signal strength in dBm (-127 to 0) of the last
|
|
||||||
message received from the peer; and
|
|
||||||
- ``time_ms`` is the time the message was received (in milliseconds since
|
|
||||||
system boot - wraps every 12 days).
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
>>> e.peers_table
|
|
||||||
{b'\xaa\xaa\xaa\xaa\xaa\xaa': [-31, 18372],
|
|
||||||
b'\xbb\xbb\xbb\xbb\xbb\xbb': [-43, 12541]}
|
|
||||||
|
|
||||||
**Note**: the ``mac`` addresses returned by `recv()` are references to
|
|
||||||
the ``peer`` key values in the **peer device table**.
|
|
||||||
|
|
||||||
**Note**: RSSI and timestamp values in the device table are updated only
|
|
||||||
when the message is read by the application.
|
|
||||||
|
|
||||||
Supporting asyncio
|
|
||||||
------------------
|
|
||||||
|
|
||||||
A supplementary module (`aioespnow`) is available to provide
|
|
||||||
:doc:`asyncio<asyncio>` support.
|
|
||||||
|
|
||||||
**Note:** Asyncio support is available on all ESP32 targets as well as those
|
|
||||||
ESP8266 boards which include the asyncio module (ie. ESP8266 devices with at
|
|
||||||
least 2MB flash memory).
|
|
||||||
|
|
||||||
A small async server example::
|
|
||||||
|
|
||||||
import network
|
|
||||||
import aioespnow
|
|
||||||
import asyncio
|
|
||||||
|
|
||||||
# A WLAN interface must be active to send()/recv()
|
|
||||||
network.WLAN(network.STA_IF).active(True)
|
|
||||||
|
|
||||||
e = aioespnow.AIOESPNow() # Returns AIOESPNow enhanced with async support
|
|
||||||
e.active(True)
|
|
||||||
peer = b'\xbb\xbb\xbb\xbb\xbb\xbb'
|
|
||||||
e.add_peer(peer)
|
|
||||||
|
|
||||||
# Send a periodic ping to a peer
|
|
||||||
async def heartbeat(e, peer, period=30):
|
|
||||||
while True:
|
|
||||||
if not await e.asend(peer, b'ping'):
|
|
||||||
print("Heartbeat: peer not responding:", peer)
|
|
||||||
else:
|
|
||||||
print("Heartbeat: ping", peer)
|
|
||||||
await asyncio.sleep(period)
|
|
||||||
|
|
||||||
# Echo any received messages back to the sender
|
|
||||||
async def echo_server(e):
|
|
||||||
async for mac, msg in e:
|
|
||||||
print("Echo:", msg)
|
|
||||||
try:
|
|
||||||
await e.asend(mac, msg)
|
|
||||||
except OSError as err:
|
|
||||||
if len(err.args) > 1 and err.args[1] == 'ESP_ERR_ESPNOW_NOT_FOUND':
|
|
||||||
e.add_peer(mac)
|
|
||||||
await e.asend(mac, msg)
|
|
||||||
|
|
||||||
async def main(e, peer, timeout, period):
|
|
||||||
asyncio.create_task(heartbeat(e, peer, period))
|
|
||||||
asyncio.create_task(echo_server(e))
|
|
||||||
await asyncio.sleep(timeout)
|
|
||||||
|
|
||||||
asyncio.run(main(e, peer, 120, 10))
|
|
||||||
|
|
||||||
.. module:: aioespnow
|
|
||||||
:synopsis: ESP-NOW :doc:`asyncio` support
|
|
||||||
|
|
||||||
.. class:: AIOESPNow()
|
|
||||||
|
|
||||||
The `AIOESPNow` class inherits all the methods of `ESPNow<espnow.ESPNow>`
|
|
||||||
and extends the interface with the following async methods.
|
|
||||||
|
|
||||||
.. method:: async AIOESPNow.arecv()
|
|
||||||
|
|
||||||
Asyncio support for `ESPNow.recv()`. Note that this method does not take a
|
|
||||||
timeout value as argument.
|
|
||||||
|
|
||||||
.. method:: async AIOESPNow.airecv()
|
|
||||||
|
|
||||||
Asyncio support for `ESPNow.irecv()`. Note that this method does not take a
|
|
||||||
timeout value as argument.
|
|
||||||
|
|
||||||
.. method:: async AIOESPNow.asend(mac, msg, sync=True)
|
|
||||||
async AIOESPNow.asend(msg)
|
|
||||||
|
|
||||||
Asyncio support for `ESPNow.send()`.
|
|
||||||
|
|
||||||
.. method:: AIOESPNow._aiter__() / async AIOESPNow.__anext__()
|
|
||||||
|
|
||||||
`AIOESPNow` also supports reading incoming messages by asynchronous
|
|
||||||
iteration using ``async for``; eg::
|
|
||||||
|
|
||||||
e = AIOESPNow()
|
|
||||||
e.active(True)
|
|
||||||
async def recv_till_halt(e):
|
|
||||||
async for mac, msg in e:
|
|
||||||
print(mac, msg)
|
|
||||||
if msg == b'halt':
|
|
||||||
break
|
|
||||||
asyncio.run(recv_till_halt(e))
|
|
||||||
|
|
||||||
Broadcast and Multicast
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
All active ESPNow clients will receive messages sent to their MAC address and
|
|
||||||
all devices (**except ESP8266 devices**) will also receive messages sent to the
|
|
||||||
*broadcast* MAC address (``b'\xff\xff\xff\xff\xff\xff'``) or any multicast
|
|
||||||
MAC address.
|
|
||||||
|
|
||||||
All ESPNow devices (including ESP8266 devices) can also send messages to the
|
|
||||||
broadcast MAC address or any multicast MAC address.
|
|
||||||
|
|
||||||
To `send()<ESPNow.send()>` a broadcast message, the broadcast (or
|
|
||||||
multicast) MAC address must first be registered using
|
|
||||||
`add_peer()<ESPNow.add_peer()>`. `send()<ESPNow.send()>` will always return
|
|
||||||
``True`` for broadcasts, regardless of whether any devices receive the
|
|
||||||
message. It is not permitted to encrypt messages sent to the broadcast
|
|
||||||
address or any multicast address.
|
|
||||||
|
|
||||||
**Note**: `ESPNow.send(None, msg)<ESPNow.send()>` will send to all registered
|
|
||||||
peers *except* the broadcast address. To send a broadcast or multicast
|
|
||||||
message, you must specify the broadcast (or multicast) MAC address as the
|
|
||||||
peer. For example::
|
|
||||||
|
|
||||||
bcast = b'\xff' * 6
|
|
||||||
e.add_peer(bcast)
|
|
||||||
e.send(bcast, "Hello World!")
|
|
||||||
|
|
||||||
ESPNow and Wifi Operation
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
ESPNow messages may be sent and received on any `active()<network.WLAN.active>`
|
|
||||||
`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:
|
|
||||||
|
|
||||||
1. Wifi Power-saving Mode (`network.WLAN.PM_PERFORMANCE`)
|
|
||||||
is automatically activated and
|
|
||||||
2. The radio on the esp device changes wifi ``channel`` to match the channel
|
|
||||||
used by the Access Point.
|
|
||||||
|
|
||||||
**Wifi Power-saving Mode:** (see `Espressif Docs <https://docs.espressif.com/
|
|
||||||
projects/esp-idf/en/latest/esp32/api-guides/
|
|
||||||
wifi.html#esp32-wi-fi-power-saving-mode>`_) The power saving mode causes the
|
|
||||||
device to turn off the radio periodically (typically for hundreds of
|
|
||||||
milliseconds), making it unreliable in receiving ESPNow messages. This can be
|
|
||||||
resolved by either of:
|
|
||||||
|
|
||||||
1. Disabling the power-saving mode on the STA_IF interface;
|
|
||||||
|
|
||||||
- Use ``sta.config(pm=sta.PM_NONE)``
|
|
||||||
|
|
||||||
2. Turning on the AP_IF interface, which will disable the power saving mode.
|
|
||||||
However, the device will then be advertising an active wifi access point.
|
|
||||||
|
|
||||||
- You **may** also choose to send your messages via the AP_IF interface, but
|
|
||||||
this is not necessary.
|
|
||||||
- ESP8266 peers must send messages to this AP_IF interface (see below).
|
|
||||||
|
|
||||||
3. Configuring ESPNow clients to retry sending messages.
|
|
||||||
|
|
||||||
**Receiving messages from an ESP8266 device:** Strangely, an ESP32 device
|
|
||||||
connected to a wifi network using method 1 or 2 above, will receive ESPNow
|
|
||||||
messages sent to the STA_IF MAC address from another ESP32 device, but will
|
|
||||||
**reject** messages from an ESP8266 device!!!. To receive messages from an
|
|
||||||
ESP8266 device, the AP_IF interface must be set to ``active(True)`` **and**
|
|
||||||
messages must be sent to the AP_IF MAC address.
|
|
||||||
|
|
||||||
**Managing wifi channels:** Any other ESPNow devices wishing to communicate with
|
|
||||||
a device which is also connected to a Wifi Access Point MUST use the same
|
|
||||||
channel. A common scenario is where one ESPNow device is connected to a wifi
|
|
||||||
router and acts as a proxy for messages from a group of sensors connected via
|
|
||||||
ESPNow:
|
|
||||||
|
|
||||||
**Proxy:** ::
|
|
||||||
|
|
||||||
import network, time, espnow
|
|
||||||
|
|
||||||
sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected
|
|
||||||
sta.connect('myssid', 'mypassword')
|
|
||||||
while not sta.isconnected(): # Wait until connected...
|
|
||||||
time.sleep(0.1)
|
|
||||||
sta.config(pm=sta.PM_NONE) # ..then disable power saving
|
|
||||||
|
|
||||||
# Print the wifi channel used AFTER finished connecting to access point
|
|
||||||
print("Proxy running on channel:", sta.config("channel"))
|
|
||||||
e = espnow.ESPNow(); e.active(True)
|
|
||||||
for peer, msg in e:
|
|
||||||
# Receive espnow messages and forward them to MQTT broker over wifi
|
|
||||||
|
|
||||||
**Sensor:** ::
|
|
||||||
|
|
||||||
import network, espnow
|
|
||||||
|
|
||||||
sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected
|
|
||||||
sta.config(channel=6) # Change to the channel used by the proxy above.
|
|
||||||
peer = b'0\xaa\xaa\xaa\xaa\xaa' # MAC address of proxy
|
|
||||||
e = espnow.ESPNow(); e.active(True);
|
|
||||||
e.add_peer(peer)
|
|
||||||
while True:
|
|
||||||
msg = read_sensor()
|
|
||||||
e.send(peer, msg)
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
Other issues to take care with when using ESPNow with wifi are:
|
|
||||||
|
|
||||||
- **Set WIFI to known state on startup:** MicroPython does not reset the wifi
|
|
||||||
peripheral after a soft reset. This can lead to unexpected behaviour. To
|
|
||||||
guarantee the wifi is reset to a known state after a soft reset make sure you
|
|
||||||
deactivate the STA_IF and AP_IF before setting them to the desired state at
|
|
||||||
startup, eg.::
|
|
||||||
|
|
||||||
import network, time
|
|
||||||
|
|
||||||
def wifi_reset(): # Reset wifi to AP_IF off, STA_IF on and disconnected
|
|
||||||
sta = network.WLAN(network.STA_IF); sta.active(False)
|
|
||||||
ap = network.WLAN(network.AP_IF); ap.active(False)
|
|
||||||
sta.active(True)
|
|
||||||
while not sta.active():
|
|
||||||
time.sleep(0.1)
|
|
||||||
sta.disconnect() # For ESP8266
|
|
||||||
while sta.isconnected():
|
|
||||||
time.sleep(0.1)
|
|
||||||
return sta, ap
|
|
||||||
|
|
||||||
sta, ap = wifi_reset()
|
|
||||||
|
|
||||||
Remember that a soft reset occurs every time you connect to the device REPL
|
|
||||||
and when you type ``ctrl-D``.
|
|
||||||
|
|
||||||
- **STA_IF and AP_IF always operate on the same channel:** the AP_IF will change
|
|
||||||
channel when you connect to a wifi network; regardless of the channel you set
|
|
||||||
for the AP_IF (see `Attention Note 3
|
|
||||||
<https://docs.espressif.com/
|
|
||||||
projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html
|
|
||||||
#_CPPv419esp_wifi_set_config16wifi_interface_tP13wifi_config_t>`_
|
|
||||||
). After all, there is really only one wifi radio on the device, which is
|
|
||||||
shared by the STA_IF and AP_IF virtual devices.
|
|
||||||
|
|
||||||
- **Disable automatic channel assignment on your wifi router:** If the wifi
|
|
||||||
router for your wifi network is configured to automatically assign the wifi
|
|
||||||
channel, it may change the channel for the network if it detects interference
|
|
||||||
from other wifi routers. When this occurs, the ESP devices connected to the
|
|
||||||
wifi network will also change channels to match the router, but other
|
|
||||||
ESPNow-only devices will remain on the previous channel and communication will
|
|
||||||
be lost. To mitigate this, either set your wifi router to use a fixed wifi
|
|
||||||
channel or configure your devices to re-scan the wifi channels if they are
|
|
||||||
unable to find their expected peers on the current channel.
|
|
||||||
|
|
||||||
- **MicroPython re-scans wifi channels when trying to reconnect:** If the esp
|
|
||||||
device is connected to a Wifi Access Point that goes down, MicroPython will
|
|
||||||
automatically start scanning channels in an attempt to reconnect to the
|
|
||||||
Access Point. This means ESPNow messages will be lost while scanning for the
|
|
||||||
AP. This can be disabled by ``sta.config(reconnects=0)``, which will also
|
|
||||||
disable the automatic reconnection after losing connection.
|
|
||||||
|
|
||||||
- Some versions of the ESP IDF only permit sending ESPNow packets from the
|
|
||||||
STA_IF interface to peers which have been registered on the same wifi
|
|
||||||
channel as the STA_IF::
|
|
||||||
|
|
||||||
ESPNOW: Peer channel is not equal to the home channel, send fail!
|
|
||||||
|
|
||||||
ESPNow and Sleep Modes
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
The `machine.lightsleep([time_ms])<machine.lightsleep>` and
|
|
||||||
`machine.deepsleep([time_ms])<machine.deepsleep>` functions can be used to put
|
|
||||||
the ESP32 and peripherals (including the WiFi and Bluetooth radios) to sleep.
|
|
||||||
This is useful in many applications to conserve battery power. However,
|
|
||||||
applications must disable the WLAN peripheral (using
|
|
||||||
`active(False)<network.WLAN.active>`) before entering light or deep sleep (see
|
|
||||||
`Sleep Modes <https://docs.espressif.com/
|
|
||||||
projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html>`_).
|
|
||||||
Otherwise the WiFi radio may not be initialised properly after wake from
|
|
||||||
sleep. If the ``STA_IF`` and ``AP_IF`` interfaces have both been set
|
|
||||||
`active(True)<network.WLAN.active()>` then both interfaces should be set
|
|
||||||
`active(False)<network.WLAN.active()>` before entering any sleep mode.
|
|
||||||
|
|
||||||
**Example:** deep sleep::
|
|
||||||
|
|
||||||
import network, machine, espnow
|
|
||||||
|
|
||||||
sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected
|
|
||||||
peer = b'0\xaa\xaa\xaa\xaa\xaa' # MAC address of peer
|
|
||||||
e = espnow.ESPNow()
|
|
||||||
e.active(True)
|
|
||||||
e.add_peer(peer) # Register peer on STA_IF
|
|
||||||
|
|
||||||
print('Sending ping...')
|
|
||||||
if not e.send(peer, b'ping'):
|
|
||||||
print('Ping failed!')
|
|
||||||
e.active(False)
|
|
||||||
sta.active(False) # Disable the wifi before sleep
|
|
||||||
print('Going to sleep...')
|
|
||||||
machine.deepsleep(10000) # Sleep for 10 seconds then reboot
|
|
||||||
|
|
||||||
**Example:** light sleep::
|
|
||||||
|
|
||||||
import network, machine, espnow
|
|
||||||
|
|
||||||
sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected
|
|
||||||
sta.config(channel=6)
|
|
||||||
peer = b'0\xaa\xaa\xaa\xaa\xaa' # MAC address of peer
|
|
||||||
e = espnow.ESPNow()
|
|
||||||
e.active(True)
|
|
||||||
e.add_peer(peer) # Register peer on STA_IF
|
|
||||||
|
|
||||||
while True:
|
|
||||||
print('Sending ping...')
|
|
||||||
if not e.send(peer, b'ping'):
|
|
||||||
print('Ping failed!')
|
|
||||||
sta.active(False) # Disable the wifi before sleep
|
|
||||||
print('Going to sleep...')
|
|
||||||
machine.lightsleep(10000) # Sleep for 10 seconds
|
|
||||||
sta.active(True)
|
|
||||||
sta.config(channel=6) # Wifi loses config after lightsleep()
|
|
||||||
|
|
||||||
@ -11,19 +11,19 @@ class FrameBuffer
|
|||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
The FrameBuffer class provides a pixel buffer which can be drawn upon with
|
The FrameBuffer class provides a pixel buffer which can be drawn upon with
|
||||||
pixels, lines, rectangles, ellipses, polygons, text and even other
|
pixels, lines, rectangles, text and even other FrameBuffer's. It is useful
|
||||||
FrameBuffers. It is useful when generating output for displays.
|
when generating output for displays.
|
||||||
|
|
||||||
For example::
|
For example::
|
||||||
|
|
||||||
import framebuf
|
import framebuf
|
||||||
|
|
||||||
# FrameBuffer needs 2 bytes for every RGB565 pixel
|
# FrameBuffer needs 2 bytes for every RGB565 pixel
|
||||||
fbuf = framebuf.FrameBuffer(bytearray(100 * 10 * 2), 100, 10, framebuf.RGB565)
|
fbuf = framebuf.FrameBuffer(bytearray(10 * 100 * 2), 10, 100, framebuf.RGB565)
|
||||||
|
|
||||||
fbuf.fill(0)
|
fbuf.fill(0)
|
||||||
fbuf.text('MicroPython!', 0, 0, 0xffff)
|
fbuf.text('MicroPython!', 0, 0, 0xffff)
|
||||||
fbuf.hline(0, 9, 96, 0xffff)
|
fbuf.hline(0, 10, 96, 0xffff)
|
||||||
|
|
||||||
Constructors
|
Constructors
|
||||||
------------
|
------------
|
||||||
@ -77,37 +77,12 @@ The following methods draw shapes onto the FrameBuffer.
|
|||||||
methods draw horizontal and vertical lines respectively up to
|
methods draw horizontal and vertical lines respectively up to
|
||||||
a given length.
|
a given length.
|
||||||
|
|
||||||
.. method:: FrameBuffer.rect(x, y, w, h, c[, f])
|
.. method:: FrameBuffer.rect(x, y, w, h, c)
|
||||||
|
.. method:: FrameBuffer.fill_rect(x, y, w, h, c)
|
||||||
|
|
||||||
Draw a rectangle at the given location, size and color.
|
Draw a rectangle at the given location, size and color. The `rect`
|
||||||
|
method draws only a 1 pixel outline whereas the `fill_rect` method
|
||||||
The optional *f* parameter can be set to ``True`` to fill the rectangle.
|
draws both the outline and interior.
|
||||||
Otherwise just a one pixel outline is drawn.
|
|
||||||
|
|
||||||
.. method:: FrameBuffer.ellipse(x, y, xr, yr, c[, f, m])
|
|
||||||
|
|
||||||
Draw an ellipse at the given location. Radii *xr* and *yr* define the
|
|
||||||
geometry; equal values cause a circle to be drawn. The *c* parameter
|
|
||||||
defines the color.
|
|
||||||
|
|
||||||
The optional *f* parameter can be set to ``True`` to fill the ellipse.
|
|
||||||
Otherwise just a one pixel outline is drawn.
|
|
||||||
|
|
||||||
The optional *m* parameter enables drawing to be restricted to certain
|
|
||||||
quadrants of the ellipse. The LS four bits determine which quadrants are
|
|
||||||
to be drawn, with bit 0 specifying Q1, b1 Q2, b2 Q3 and b3 Q4. Quadrants
|
|
||||||
are numbered counterclockwise with Q1 being top right.
|
|
||||||
|
|
||||||
.. method:: FrameBuffer.poly(x, y, coords, c[, f])
|
|
||||||
|
|
||||||
Given a list of coordinates, draw an arbitrary (convex or concave) closed
|
|
||||||
polygon at the given x, y location using the given color.
|
|
||||||
|
|
||||||
The *coords* must be specified as a :mod:`array` of integers, e.g.
|
|
||||||
``array('h', [x0, y0, x1, y1, ... xn, yn])``.
|
|
||||||
|
|
||||||
The optional *f* parameter can be set to ``True`` to fill the polygon.
|
|
||||||
Otherwise just a one pixel outline is drawn.
|
|
||||||
|
|
||||||
Drawing text
|
Drawing text
|
||||||
------------
|
------------
|
||||||
@ -133,9 +108,7 @@ Other methods
|
|||||||
Draw another FrameBuffer on top of the current one at the given coordinates.
|
Draw another FrameBuffer on top of the current one at the given coordinates.
|
||||||
If *key* is specified then it should be a color integer and the
|
If *key* is specified then it should be a color integer and the
|
||||||
corresponding color will be considered transparent: all pixels with that
|
corresponding color will be considered transparent: all pixels with that
|
||||||
color value will not be drawn. (If the *palette* is specified then the *key*
|
color value will not be drawn.
|
||||||
is compared to the value from *palette*, not to the value directly from
|
|
||||||
*fbuf*.)
|
|
||||||
|
|
||||||
The *palette* argument enables blitting between FrameBuffers with differing
|
The *palette* argument enables blitting between FrameBuffers with differing
|
||||||
formats. Typical usage is to render a monochrome or grayscale glyph/icon to
|
formats. Typical usage is to render a monochrome or grayscale glyph/icon to
|
||||||
|
|||||||
@ -24,7 +24,7 @@ Functions
|
|||||||
|
|
||||||
.. function:: mem_alloc()
|
.. function:: mem_alloc()
|
||||||
|
|
||||||
Return the number of bytes of heap RAM that are allocated by Python code.
|
Return the number of bytes of heap RAM that are allocated.
|
||||||
|
|
||||||
.. admonition:: Difference to CPython
|
.. admonition:: Difference to CPython
|
||||||
:class: attention
|
:class: attention
|
||||||
@ -33,8 +33,8 @@ Functions
|
|||||||
|
|
||||||
.. function:: mem_free()
|
.. function:: mem_free()
|
||||||
|
|
||||||
Return the number of bytes of heap RAM that is available for Python
|
Return the number of bytes of available heap RAM, or -1 if this amount
|
||||||
code to allocate, or -1 if this amount is not known.
|
is not known.
|
||||||
|
|
||||||
.. admonition:: Difference to CPython
|
.. admonition:: Difference to CPython
|
||||||
:class: attention
|
:class: attention
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user