Merge branch 'micropython:master' into master

pull/14422/head
kldonnelly 2024-03-22 18:16:59 +13:00 zatwierdzone przez GitHub
commit ecf441049e
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
1812 zmienionych plików z 59776 dodań i 43975 usunięć

Wyświetl plik

@ -1,3 +1,18 @@
# 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

2
.gitattributes vendored
Wyświetl plik

@ -8,10 +8,12 @@
# These are binary so should never be modified by git.
*.a binary
*.ico binary
*.png binary
*.jpg binary
*.dxf binary
*.mpy binary
*.der binary
# These should also not be modified by git.
tests/basics/string_cr_conversion.py -text

Wyświetl plik

@ -1,25 +0,0 @@
---
name: Bug report
about: Report an issue
title: ''
labels: bug
assignees: ''
---
* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please use the Discussions tab or raise a documentation request instead.
* In your issue, please include a clear and concise description of what the bug is, the expected output, and how to replicate it.
* If this issue involves external hardware, please include links to relevant datasheets and schematics.
* If you are seeing code being executed incorrectly, please provide a minimal example and expected output (e.g. comparison to CPython).
* For build issues, please include full details of your environment, compiler versions, command lines, and build output.
* Please provide as much information as possible about the version of MicroPython you're running, such as:
- firmware file name
- git commit hash and port/board
- version information shown in the REPL (hit Ctrl-B to see the startup message)
* Remove all placeholder text above before submitting.

Wyświetl plik

@ -0,0 +1,107 @@
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).
- type: checkboxes
id: terms
attributes:
label: Checks
description: |
Before submitting your bug report, please go over these check points:
options:
- label: |
I 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.
required: true
- label: |
I've searched for [existing issues](https://github.com/micropython/micropython/issues) matching this bug, and didn't find any.
required: true
- 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: markdown
attributes:
value: |
Thanks for taking the time to help improve MicroPython.

Wyświetl plik

@ -1,16 +0,0 @@
---
name: Documentation issue
about: Report areas of the documentation or examples that need improvement
title: 'docs: '
labels: documentation
assignees: ''
---
* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please use the Discussions tab instead.
* Describe what was missing from the documentation and/or what was incorrect/incomplete.
* If possible, please link to the relevant page on https://docs.micropython.org/
* Remove all placeholder text above before submitting.

Wyświetl plik

@ -0,0 +1,44 @@
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.
- type: checkboxes
id: terms
attributes:
label: Checks
description: |
Before submitting your bug report, please go over these check points:
options:
- label: |
I 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.
required: true
- label: |
I've searched for [existing issues](https://github.com/micropython/micropython/issues) and didn't find any that matched.
required: true
- 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: markdown
attributes:
value: |
Thanks for taking the time to help improve MicroPython.

Wyświetl plik

@ -1,24 +0,0 @@
---
name: Feature request
about: Request a feature or improvement
title: ''
labels: enhancement
assignees: ''
---
* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please use the Discussions tab or raise a documentation request instead.
* Describe the feature you'd like to see added to MicroPython. In particular, what does this feature enable and why is it useful. MicroPython aims to strike a balance between functionality and code size, so please consider whether this feature can be optionally enabled and whether it can be provided in other ways (e.g. pure-Python library).
* For core Python features, where possible please include a link to the relevant PEP.
* For new architectures / ports / boards, please provide links to relevant documentation, specifications, and toolchains. Any information about the popularity and unique features about this hardware would also be useful.
* For features for existing ports (e.g. new peripherals or microcontroller features), please describe which port(s) it applies too, and whether this is could be an extension to the machine API or a port-specific module?
* For drivers (e.g. for external hardware), please link to datasheets and/or existing drivers from other sources.
* Who do you expect will implement the feature you are requesting? Would you be willing to sponsor this work?
* Remove all placeholder text above before submitting.

Wyświetl plik

@ -0,0 +1,65 @@
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.
- type: checkboxes
id: terms
attributes:
label: Checks
description: |
Before submitting your feature request, please go over these check points:
options:
- label: |
I 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.
required: true
- label: |
I've searched for [existing issues](https://github.com/micropython/micropython/issues) regarding this feature, and didn't find any.
required: true
- 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: checkboxes
id: implementation
attributes:
label: Implementation
options:
- label: I intend to implement this feature and would submit a Pull Request if desirable.
- label: I hope the MicroPython maintainers or community will implement this feature.
- label: I would like to [Sponsor](https://github.com/sponsors/micropython#sponsors) development of this feature.
- type: markdown
attributes:
value: |
Thanks for taking the time to suggest improvements for MicroPython.

Wyświetl plik

@ -1,16 +0,0 @@
---
name: Security report
about: Report a security issue or vulnerability in MicroPython
title: ''
labels: security
assignees: ''
---
* If you need to raise this issue privately with the MicroPython team, please email contact@micropython.org instead.
* Include a clear and concise description of what the security issue is.
* What does this issue allow an attacker to do?
* Remove all placeholder text above before submitting.

Wyświetl plik

@ -0,0 +1,59 @@
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.
- type: checkboxes
id: terms
attributes:
label: Checks
description: |
Before submitting your bug report, please go over these check points:
options:
- label: |
I 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.
required: true
- label: I wish to report a specific security issue that is **not readily exploitable and does not have high impact** for MicroPython developers or users.
required: true
- label: |
I've searched for [existing issues](https://github.com/micropython/micropython/issues) and didn't find any that matched.
required: true
- 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

16
.github/workflows/biome.yml vendored 100644
Wyświetl plik

@ -0,0 +1,16 @@
name: JavaScript code lint and formatting with Biome
on: [push, pull_request]
jobs:
eslint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Biome
uses: biomejs/setup-biome@v2
with:
version: 1.5.3
- name: Run Biome
run: biome ci --indent-style=space --indent-width=4 tests/ ports/webassembly

Wyświetl plik

@ -11,20 +11,10 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
- name: Install packages
run: source tools/ci.sh && ci_code_formatting_setup
run: source tools/ci.sh && ci_c_code_formatting_setup
- name: Run code formatting
run: source tools/ci.sh && ci_code_formatting_run
run: source tools/ci.sh && ci_c_code_formatting_run
- name: Check code formatting
run: git diff --exit-code
code-spelling:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- name: Install packages
run: source tools/ci.sh && ci_code_spell_setup
- name: Run spell checker
run: source tools/ci.sh && ci_code_spell_run

Wyświetl plik

@ -36,7 +36,7 @@ jobs:
run: echo $PR_NUMBER > pr_number
- name: Upload diff
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: code-size-report
path: |

Wyświetl plik

@ -15,7 +15,7 @@ jobs:
steps:
- name: 'Download artifact'
id: download-artifact
uses: actions/github-script@v6
uses: actions/github-script@v7
with:
result-encoding: string
script: |
@ -56,7 +56,7 @@ jobs:
run: unzip code-size-report.zip
- name: Post comment to pull request
if: steps.download-artifact.outputs.result == 'ok'
uses: actions/github-script@v6
uses: actions/github-script@v7
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |

13
.github/workflows/codespell.yml vendored 100644
Wyświetl plik

@ -0,0 +1,13 @@
name: Check spelling with codespell
on: [push, pull_request]
jobs:
codespell:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# codespell version should be kept in sync with .pre-commit-config.yml
- run: pip install --user codespell==2.2.6 tomli
- run: codespell

Wyświetl plik

@ -13,6 +13,6 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: '100'
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
- name: Check commit message formatting
run: source tools/ci.sh && ci_commit_formatting_run

Wyświetl plik

@ -1,6 +1,7 @@
name: Build docs
on:
push:
pull_request:
paths:
- docs/**
@ -15,8 +16,8 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
- name: Install Python packages
run: pip install Sphinx
run: pip install -r docs/requirements.txt
- name: Build docs
run: make -C docs/ html

Wyświetl plik

@ -16,13 +16,13 @@ jobs:
# 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@v4
- 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@v3
uses: actions/upload-artifact@v4
with:
name: mpremote
path: |

Wyświetl plik

@ -18,11 +18,40 @@ concurrency:
cancel-in-progress: true
jobs:
build_idf50:
build_idf:
strategy:
fail-fast: false
matrix:
ci_func: # names are functions in ci.sh
- esp32_build_cmod_spiram_s2
- esp32_build_s3_c3
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_esp32_idf50_setup
- name: Build
run: source tools/ci.sh && ci_esp32_build
- id: idf_ver
name: Read the ESP-IDF version
run: source tools/ci.sh && echo "IDF_VER=$IDF_VER" | tee "$GITHUB_OUTPUT"
- name: Cached ESP-IDF install
id: cache_esp_idf
uses: actions/cache@v4
with:
path: |
./esp-idf/
~/.espressif/
!~/.espressif/dist/
~/.cache/pip/
key: esp-idf-${{ steps.idf_ver.outputs.IDF_VER }}
- name: Install ESP-IDF packages
if: steps.cache_esp_idf.outputs.cache-hit != 'true'
run: source tools/ci.sh && ci_esp32_idf_setup
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: esp32-${{ matrix.ci_func }}
- name: Build ci_${{matrix.ci_func }}
run: source tools/ci.sh && ci_${{ matrix.ci_func }}

Wyświetl plik

@ -20,8 +20,13 @@ concurrency:
jobs:
build:
runs-on: ubuntu-20.04
defaults:
run:
working-directory: 'micropython repo' # test build with space in path
steps:
- uses: actions/checkout@v4
with:
path: 'micropython repo'
- name: Install packages
run: source tools/ci.sh && ci_mimxrt_setup
- name: Build

Wyświetl plik

@ -20,8 +20,13 @@ concurrency:
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: 'micropython repo' # test build with space in path
steps:
- uses: actions/checkout@v4
with:
path: 'micropython repo'
- name: Install packages
run: source tools/ci.sh && ci_rp2_setup
- name: Build

Wyświetl plik

@ -18,20 +18,19 @@ concurrency:
cancel-in-progress: true
jobs:
build_pyb:
build_stm32:
strategy:
fail-fast: false
matrix:
ci_func: # names are functions in ci.sh
- stm32_pyb_build
- stm32_nucleo_build
- stm32_misc_build
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_stm32_setup
- name: Build
run: source tools/ci.sh && ci_stm32_pyb_build
- name: Build ci_${{matrix.ci_func }}
run: source tools/ci.sh && ci_${{ matrix.ci_func }}
build_nucleo:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_stm32_setup
- name: Build
run: source tools/ci.sh && ci_stm32_nucleo_build

Wyświetl plik

@ -1,28 +0,0 @@
name: teensy port
on:
push:
pull_request:
paths:
- '.github/workflows/*.yml'
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/teensy/**'
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_teensy_setup
- name: Build
run: source tools/ci.sh && ci_teensy_build

Wyświetl plik

@ -55,6 +55,18 @@ jobs:
if: failure()
run: tests/run-tests.py --print-failures
standard_v2:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: source tools/ci.sh && ci_unix_standard_v2_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_standard_v2_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
coverage:
runs-on: ubuntu-latest
steps:
@ -184,7 +196,7 @@ jobs:
runs-on: macos-11.0
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: '3.8'
- name: Build

Wyświetl plik

@ -18,7 +18,134 @@ concurrency:
cancel-in-progress: true
jobs:
build:
build-vs:
strategy:
fail-fast: false
matrix:
platform: [x86, x64]
configuration: [Debug, Release]
variant: [dev, standard]
visualstudio: ['2017', '2019', '2022']
include:
- visualstudio: '2017'
runner: windows-latest
vs_version: '[15, 16)'
- visualstudio: '2019'
runner: windows-2019
vs_version: '[16, 17)'
- visualstudio: '2022'
runner: windows-2022
vs_version: '[17, 18)'
# trim down the number of jobs in the matrix
exclude:
- variant: standard
configuration: Debug
- visualstudio: '2019'
configuration: Debug
runs-on: ${{ matrix.runner }}
steps:
- name: Install Visual Studio 2017
if: matrix.visualstudio == '2017'
run: |
choco install visualstudio2017buildtools
choco install visualstudio2017-workload-vctools
choco install windows-sdk-8.1
- uses: microsoft/setup-msbuild@v2
with:
vs-version: ${{ matrix.vs_version }}
- uses: actions/setup-python@v5
if: matrix.runner == 'windows-2019'
with:
python-version: '3.9'
- uses: actions/checkout@v4
- name: Build mpy-cross.exe
run: msbuild mpy-cross\mpy-cross.vcxproj -maxcpucount -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }}
- name: Update submodules
run: git submodule update --init lib/micropython-lib
- name: Build micropython.exe
run: msbuild ports\windows\micropython.vcxproj -maxcpucount -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }} -property:PyVariant=${{ matrix.variant }}
- name: Get micropython.exe path
id: get_path
run: |
$exePath="$(msbuild ports\windows\micropython.vcxproj -nologo -v:m -t:ShowTargetPath -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }} -property:PyVariant=${{ matrix.variant }})"
echo ("micropython=" + $exePath.Trim()) >> $env:GITHUB_OUTPUT
- name: Run tests
id: test
env:
MICROPY_MICROPYTHON: ${{ steps.get_path.outputs.micropython }}
working-directory: tests
run: python run-tests.py
- name: Print failures
if: failure() && steps.test.conclusion == 'failure'
working-directory: tests
run: python run-tests.py --print-failures
- name: Run mpy tests
id: test_mpy
env:
MICROPY_MICROPYTHON: ${{ steps.get_path.outputs.micropython }}
working-directory: tests
run: python run-tests.py --via-mpy -d basics float micropython
- name: Print mpy failures
if: failure() && steps.test_mpy.conclusion == 'failure'
working-directory: tests
run: python run-tests.py --print-failures
build-mingw:
strategy:
fail-fast: false
matrix:
variant: [dev, standard]
sys: [mingw32, mingw64]
include:
- sys: mingw32
env: i686
- sys: mingw64
env: x86_64
runs-on: windows-2022
env:
CHERE_INVOKING: enabled_from_arguments
defaults:
run:
shell: msys2 {0}
steps:
- name: Get Python path
id: python_path
shell: python
run: |
import os
import sys
output = f"python={os.fspath(sys.executable)}"
print(output)
with open(os.environ["GITHUB_OUTPUT"], "w") as f:
f.write(output)
- uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.sys }}
update: true
install: >-
make
mingw-w64-${{ matrix.env }}-gcc
pkg-config
python3
git
diffutils
- uses: actions/checkout@v4
- name: Build mpy-cross.exe
run: make -C mpy-cross -j2
- name: Update submodules
run: make -C ports/windows VARIANT=${{ matrix.variant }} submodules
- name: Build micropython.exe
run: make -C ports/windows -j2 VARIANT=${{ matrix.variant }}
- name: Run tests
id: test
# msys python breaks tests so we need to use "real" windows python
run: MICROPY_CPYTHON3=$(cygpath "${{ steps.python_path.outputs.python }}") make -C ports/windows test_full VARIANT=${{ matrix.variant }}
- name: Print failures
if: failure() && steps.test.conclusion == 'failure'
working-directory: tests
run: python run-tests.py --print-failures
cross-build-on-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

Wyświetl plik

@ -1,10 +1,13 @@
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Python code lint with ruff
name: Python code lint and formatting with ruff
on: [push, pull_request]
jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install --user ruff
- run: ruff --format=github .
# 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 .

8
.gitmodules vendored
Wyświetl plik

@ -9,7 +9,7 @@
url = https://github.com/lwip-tcpip/lwip.git
[submodule "lib/berkeley-db-1.xx"]
path = lib/berkeley-db-1.xx
url = https://github.com/pfalcon/berkeley-db-1.xx
url = https://github.com/micropython/berkeley-db-1.xx
[submodule "lib/stm32lib"]
path = lib/stm32lib
url = https://github.com/micropython/stm32lib
@ -59,3 +59,9 @@
[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

Wyświetl plik

@ -2,8 +2,8 @@ repos:
- repo: local
hooks:
- id: codeformat
name: MicroPython codeformat.py for changed files
entry: tools/codeformat.py -v -f
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
@ -12,6 +12,16 @@ repos:
verbose: true
stages: [commit-msg]
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.265
# 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

Wyświetl plik

@ -53,13 +53,16 @@ are then certifying and signing off against the following:
Code auto-formatting
====================
Both C and Python code are auto-formatted using the `tools/codeformat.py`
script. This uses [uncrustify](https://github.com/uncrustify/uncrustify) to
format C code and [black](https://github.com/psf/black) to format Python code.
After making changes, and before committing, run this tool to reformat your
changes to the correct style. Without arguments this tool will reformat all
source code (and may take some time to run). Otherwise pass as arguments to
the tool the files that changed and it will only reformat those.
Both C and Python code formatting are controlled for consistency across the
MicroPython codebase. C code is formatted using the `tools/codeformat.py`
script which uses [uncrustify](https://github.com/uncrustify/uncrustify).
Python code is linted and formatted using
[ruff & ruff format](https://github.com/astral-sh/ruff).
After making changes, and before committing, run `tools/codeformat.py` to
reformat your C code and `ruff format` for any Python code. Without
arguments this tool will reformat all source code (and may take some time
to run). Otherwise pass as arguments to the tool the files that changed,
and it will only reformat those.
uncrustify
==========
@ -101,6 +104,22 @@ This command may work, please raise a new Issue if it doesn't:
curl -L https://github.com/Homebrew/homebrew-core/raw/2b07d8192623365078a8b855a164ebcdf81494a6/Formula/uncrustify.rb > uncrustify.rb && brew install uncrustify.rb && rm uncrustify.rb
```
Code spell checking
===================
Code spell checking is done using [codespell](https://github.com/codespell-project/codespell#codespell)
and runs in a GitHub action in CI. Codespell is configured via `pyproject.toml`
to avoid false positives. It is recommended run codespell before submitting a
PR. To simplify this, codespell is configured as a pre-commit hook and will be
installed if you run `pre-commit install` (see below).
If you want to install and run codespell manually, you can do so by running:
```
$ pip install codespell tomli
$ codespell
```
Automatic Pre-Commit Hooks
==========================
@ -151,12 +170,22 @@ Tips:
* To ignore the pre-commit message format check temporarily, start the commit
message subject line with "WIP" (for "Work In Progress").
Running pre-commit manually
===========================
Once pre-commit is installed as per the previous section it can be manually
run against the MicroPython python codebase to update file formatting on
demand, with either:
* `pre-commit run --all-files` to fix all files in the MicroPython codebase
* `pre-commit run --file ./path/to/my/file` to fix just one file
* `pre-commit run --file ./path/to/my/folder/*` to fix just one folder
Python code conventions
=======================
Python code follows [PEP 8](https://legacy.python.org/dev/peps/pep-0008/) and
is auto-formatted using [black](https://github.com/psf/black) with a line-length
of 99 characters.
is auto-formatted using [ruff format](https://docs.astral.sh/ruff/formatter)
with a line-length of 99 characters.
Naming conventions:
- Module names are short and all lowercase; eg pyb, stm.

Wyświetl plik

@ -48,12 +48,14 @@ used during the build process and is not part of the compiled source code.
/cmsis (BSD-3-clause)
/crypto-algorithms (NONE)
/libhydrogen (ISC)
/libmetal (BSD-3-clause)
/littlefs (BSD-3-clause)
/lwip (BSD-3-clause)
/mynewt-nimble (Apache-2.0)
/nrfx (BSD-3-clause)
/nxp_driver (BSD-3-Clause)
/oofatfs (BSD-1-clause)
/open-amp (BSD-3-clause)
/pico-sdk (BSD-3-clause)
/re15 (BSD-3-clause)
/stm32lib (BSD-3-clause)
@ -69,6 +71,8 @@ used during the build process and is not part of the compiled source code.
/FreeRTOS (GPL-2.0 with FreeRTOS exception)
/esp32
/ppp_set_auth.* (Apache-2.0)
/rp2
/mutex_extra.c (BSD-3-clause)
/stm32
/usbd*.c (MCD-ST Liberty SW License Agreement V2)
/stm32_it.* (MIT + BSD-3-clause)
@ -78,8 +82,6 @@ used during the build process and is not part of the compiled source code.
/*/stm32*.h (BSD-3-clause)
/usbdev (MCD-ST Liberty SW License Agreement V2)
/usbhost (MCD-ST Liberty SW License Agreement V2)
/teensy
/core (PJRC.COM)
/zephyr
/src (Apache-2.0)
/tools

Wyświetl plik

@ -1,4 +1,4 @@
[![CI badge](https://github.com/micropython/micropython/workflows/unix%20port/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![codecov](https://codecov.io/gh/micropython/micropython/branch/master/graph/badge.svg?token=I92PfD05sD)](https://codecov.io/gh/micropython/micropython)
[![Unix CI badge](https://github.com/micropython/micropython/actions/workflows/ports_unix.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![STM32 CI badge](https://github.com/micropython/micropython/actions/workflows/ports_stm32.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![Docs CI badge](https://github.com/micropython/micropython/actions/workflows/docs.yml/badge.svg)](https://docs.micropython.org/) [![codecov](https://codecov.io/gh/micropython/micropython/branch/master/graph/badge.svg?token=I92PfD05sD)](https://codecov.io/gh/micropython/micropython)
The MicroPython project
=======================
@ -119,7 +119,6 @@ In addition, the following ports are provided in this repository:
- [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)
- [teensy](ports/teensy) -- Teensy 3.x.
- [webassembly](ports/webassembly) -- Emscripten port targeting browsers and NodeJS.
- [zephyr](ports/zephyr) -- Zephyr RTOS.

Wyświetl plik

@ -19,55 +19,56 @@ import os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('.'))
sys.path.insert(0, os.path.abspath("."))
# The MICROPY_VERSION env var should be "vX.Y.Z" (or unset).
micropy_version = os.getenv("MICROPY_VERSION") or "latest"
micropy_all_versions = (os.getenv("MICROPY_ALL_VERSIONS") or "latest").split(",")
url_pattern = "%s/en/%%s" % (os.getenv("MICROPY_URL_PREFIX") or "/",)
# The members of the html_context dict are available inside topindex.html
micropy_version = os.getenv('MICROPY_VERSION') or 'latest'
micropy_all_versions = (os.getenv('MICROPY_ALL_VERSIONS') or 'latest').split(',')
url_pattern = '%s/en/%%s' % (os.getenv('MICROPY_URL_PREFIX') or '/',)
html_context = {
'cur_version':micropy_version,
'all_versions':[
(ver, url_pattern % ver) for ver in micropy_all_versions
"cur_version": micropy_version,
"all_versions": [(ver, url_pattern % ver) for ver in micropy_all_versions],
"downloads": [
("PDF", url_pattern % micropy_version + "/micropython-docs.pdf"),
],
'downloads':[
('PDF', url_pattern % micropy_version + '/micropython-docs.pdf'),
],
'is_release': micropy_version != 'latest',
"is_release": micropy_version != "latest",
}
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.doctest',
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'sphinx.ext.coverage',
"sphinx.ext.autodoc",
"sphinx.ext.doctest",
"sphinx.ext.intersphinx",
"sphinx.ext.todo",
"sphinx.ext.coverage",
"sphinxcontrib.jquery",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['templates']
templates_path = ["templates"]
# The suffix of source filenames.
source_suffix = '.rst'
source_suffix = ".rst"
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# General information about the project.
project = 'MicroPython'
copyright = '- The MicroPython Documentation is Copyright © 2014-2023, Damien P. George, Paul Sokolovsky, and contributors'
project = "MicroPython"
copyright = "- The MicroPython Documentation is Copyright © 2014-2023, Damien P. George, Paul Sokolovsky, and contributors"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@ -79,41 +80,41 @@ version = release = micropy_version
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['build', '.venv']
exclude_patterns = ["build", ".venv"]
# The reST default role (used for this markup: `text`) to use for all
# documents.
default_role = 'any'
default_role = "any"
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# keep_warnings = False
# Global include files. Sphinx docs suggest using rst_epilog in preference
# of rst_prolog, so we follow. Absolute paths below mean "from the base
@ -125,144 +126,148 @@ rst_epilog = """
# -- Options for HTML output ----------------------------------------------
# on_rtd is whether we are on readthedocs.org
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
if not on_rtd: # only import and set the theme if we're building docs locally
try:
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
except:
html_theme = 'default'
html_theme_path = ['.']
html_theme = "default"
html_theme_path = ["."]
else:
html_theme_path = ['.']
html_theme_path = ["."]
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = ['.']
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = '../../logo/trans-logo.png'
# html_logo = '../../logo/trans-logo.png'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = 'static/favicon.ico'
html_favicon = "static/favicon.ico"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['static']
html_static_path = ["static"]
# Add a custom CSS file for HTML generation
html_css_files = [
'custom.css',
"custom.css",
]
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
html_last_updated_fmt = '%d %b %Y'
html_last_updated_fmt = "%d %b %Y"
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
html_additional_pages = {"index": "topindex.html"}
# If false, no module index is generated.
#html_domain_indices = True
# html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'MicroPythondoc'
htmlhelp_basename = "MicroPythondoc"
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Include 3 levels of headers in PDF ToC
'preamble': r'\setcounter{tocdepth}{2}',
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Include 3 levels of headers in PDF ToC
"preamble": r"\setcounter{tocdepth}{2}",
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'MicroPython.tex', 'MicroPython Documentation',
'Damien P. George, Paul Sokolovsky, and contributors', 'manual'),
(
master_doc,
"MicroPython.tex",
"MicroPython Documentation",
"Damien P. George, Paul Sokolovsky, and contributors",
"manual",
),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# latex_domain_indices = True
# Enable better Unicode support so that `make latexpdf` doesn't fail
latex_engine = "xelatex"
@ -272,12 +277,17 @@ latex_engine = "xelatex"
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'micropython', 'MicroPython Documentation',
['Damien P. George, Paul Sokolovsky, and contributors'], 1),
(
"index",
"micropython",
"MicroPython Documentation",
["Damien P. George, Paul Sokolovsky, and contributors"],
1,
),
]
# If true, show URL addresses after external links.
#man_show_urls = False
# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
@ -286,23 +296,29 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'MicroPython', 'MicroPython Documentation',
'Damien P. George, Paul Sokolovsky, and contributors', 'MicroPython', 'One line description of project.',
'Miscellaneous'),
(
master_doc,
"MicroPython",
"MicroPython Documentation",
"Damien P. George, Paul Sokolovsky, and contributors",
"MicroPython",
"One line description of project.",
"Miscellaneous",
),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
# texinfo_no_detailmenu = False
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'python': ('https://docs.python.org/3.5', None)}
intersphinx_mapping = {"python": ("https://docs.python.org/3.5", None)}

Wyświetl plik

@ -98,7 +98,7 @@ Then also edit ``py/lexer.c`` to add the new keyword literal text:
.. code-block:: c
:emphasize-lines: 12
STATIC const char *const tok_kw[] = {
static const char *const tok_kw[] = {
...
"or",
"pass",
@ -157,7 +157,7 @@ The most relevant method you should know about is this:
mp_compile_to_raw_code(parse_tree, source_file, is_repl, &cm);
// Create and return a function object that executes the outer module.
return mp_make_function_from_raw_code(cm.rc, cm.context, NULL);
return mp_make_function_from_proto_fun(cm.rc, cm.context, NULL);
}
The compiler compiles the code in four passes: scope, stack size, code size and emit.
@ -301,7 +301,7 @@ code statement:
.. code-block:: c
STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
static void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
vtype_kind_t vtype;
emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
if (vtype == VTYPE_PYOBJ) {

Wyświetl plik

@ -112,7 +112,7 @@ Check that you have Python available on your system:
.. code-block:: bash
$ python3
Python 3.5.0 (default, Jul 17 2020, 14:04:10)
Python 3.5.0 (default, Jul 17 2020, 14:04:10)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
@ -245,7 +245,7 @@ that you use a virtual environment:
$ python3 -m venv env
$ source env/bin/activate
$ pip install sphinx
$ pip install -r docs/requirements.txt
Navigate to the ``docs`` directory:

Wyświetl plik

@ -48,16 +48,16 @@ hypothetical new module ``subsystem`` in the file ``modsubsystem.c``:
#if MICROPY_PY_SUBSYSTEM
// info()
STATIC mp_obj_t py_subsystem_info(void) {
static mp_obj_t py_subsystem_info(void) {
return MP_OBJ_NEW_SMALL_INT(42);
}
MP_DEFINE_CONST_FUN_OBJ_0(subsystem_info_obj, py_subsystem_info);
STATIC const mp_rom_map_elem_t mp_module_subsystem_globals_table[] = {
static const mp_rom_map_elem_t mp_module_subsystem_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_subsystem) },
{ MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&subsystem_info_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_subsystem_globals, mp_module_subsystem_globals_table);
static MP_DEFINE_CONST_DICT(mp_module_subsystem_globals, mp_module_subsystem_globals_table);
const mp_obj_module_t mp_module_subsystem = {
.base = { &mp_type_module },

Wyświetl plik

@ -128,7 +128,7 @@ The file ``factorial.c`` contains:
#include "py/dynruntime.h"
// Helper function to compute factorial
STATIC mp_int_t factorial_helper(mp_int_t x) {
static mp_int_t factorial_helper(mp_int_t x) {
if (x == 0) {
return 1;
}
@ -136,7 +136,7 @@ The file ``factorial.c`` contains:
}
// This is the function which will be called from Python, as factorial(x)
STATIC mp_obj_t factorial(mp_obj_t x_obj) {
static mp_obj_t factorial(mp_obj_t x_obj) {
// Extract the integer from the MicroPython input object
mp_int_t x = mp_obj_get_int(x_obj);
// Calculate the factorial
@ -145,7 +145,7 @@ The file ``factorial.c`` contains:
return mp_obj_new_int(result);
}
// Define a Python reference to the function above
STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial);
static MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial);
// This is the entry point and is called when the module is imported
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {

Wyświetl plik

@ -83,7 +83,7 @@ The basic MicroPython firmware is implemented in the main port file, e.g ``main.
}
// There is no filesystem so opening a file raises an exception.
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
mp_raise_OSError(MP_ENOENT);
}
@ -262,17 +262,17 @@ To add a custom module like ``myport``, first add the module definition in a fil
#include "py/runtime.h"
STATIC mp_obj_t myport_info(void) {
static mp_obj_t myport_info(void) {
mp_printf(&mp_plat_print, "info about my port\n");
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(myport_info_obj, myport_info);
static MP_DEFINE_CONST_FUN_OBJ_0(myport_info_obj, myport_info);
STATIC const mp_rom_map_elem_t myport_module_globals_table[] = {
static const mp_rom_map_elem_t myport_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_myport) },
{ MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&myport_info_obj) },
};
STATIC MP_DEFINE_CONST_DICT(myport_module_globals, myport_module_globals_table);
static MP_DEFINE_CONST_DICT(myport_module_globals, myport_module_globals_table);
const mp_obj_module_t myport_module = {
.base = { &mp_type_module },

Wyświetl plik

@ -0,0 +1,33 @@
.. Preamble section inserted into generated output
Positional-only Parameters
--------------------------
To save code size, many functions that accept keyword arguments in CPython only accept positional arguments in MicroPython.
MicroPython marks positional-only parameters in the same way as CPython, by inserting a ``/`` to mark the end of the positional parameters. Any function whose signature ends in ``/`` takes *only* positional arguments. For more details, see `PEP 570 <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)

Wyświetl plik

@ -105,4 +105,4 @@ Changes to built-in modules:
.. rubric:: Notes
.. [#ftimenanosec] Only :func:`time.time_ns` is implemented.
.. [#ftimenanosec] Only :func:`time.time_ns` is implemented.

Wyświetl plik

@ -101,7 +101,7 @@ A useful function for connecting to your local WiFi network is::
print('network config:', wlan.ifconfig())
Once the network is established the :mod:`socket <socket>` module can be used
to create and use TCP/UDP sockets as usual, and the ``urequests`` module for
to create and use TCP/UDP sockets as usual, and the ``requests`` module for
convenient HTTP requests.
After a call to ``wlan.connect()``, the device will by default retry to connect
@ -128,6 +128,7 @@ The keyword arguments for the constructor defining the PHY type and interface ar
- 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
@ -141,7 +142,7 @@ 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),
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)
@ -330,6 +331,19 @@ 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)
----------------------------------
@ -637,15 +651,15 @@ SD card
See :ref:`machine.SDCard <machine.SDCard>`. ::
import machine, os
import machine, os, vfs
# Slot 2 uses pins sck=18, cs=5, miso=19, mosi=23
sd = machine.SDCard(slot=2)
os.mount(sd, '/sd') # mount
vfs.mount(sd, '/sd') # mount
os.listdir('/sd') # list directory contents
os.umount('/sd') # eject
vfs.umount('/sd') # eject
RMT
---

Wyświetl plik

@ -201,10 +201,12 @@ class Lock
TCP stream connections
----------------------
.. function:: open_connection(host, port)
.. 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
@ -212,12 +214,14 @@ TCP stream connections
This is a coroutine.
.. function:: start_server(callback, host, port, backlog=5)
.. 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.

Wyświetl plik

@ -312,7 +312,7 @@ Broadcaster Role (Advertiser)
in all broadcasts, and *resp_data* is send in reply to an active scan.
**Note:** if *adv_data* (or *resp_data*) is ``None``, then the data passed
to the previous call to ``gap_advertise`` will be re-used. This allows a
to the previous call to ``gap_advertise`` will be reused. This allows a
broadcaster to resume advertising with just ``gap_advertise(interval_us)``.
To clear the advertising payload pass an empty ``bytes``, i.e. ``b''``.
@ -722,7 +722,7 @@ Pairing and bonding
and ``_IRQ_SET_SECRET`` events.
**Note:** This is currently only supported when using the NimBLE stack on
STM32 and Unix (not ESP32).
ESP32, STM32 and Unix.
.. method:: BLE.gap_pair(conn_handle, /)

Wyświetl plik

@ -18,7 +18,9 @@ Classes
appends and pops from either side of the deque. New deques are created
using the following arguments:
- *iterable* must be the empty tuple, and the new deque is created empty.
- *iterable* is an iterable used to populate the deque when it is
created. It can be an empty tuple or list to create a deque that
is initially empty.
- *maxlen* must be specified and the deque will be bounded to this
maximum length. Once the deque is full, any new items added will
@ -26,18 +28,37 @@ Classes
- The optional *flags* can be 1 to check for overflow when adding items.
As well as supporting `bool` and `len`, deque objects have the following
methods:
Deque objects support `bool`, `len`, iteration and subscript load and store.
They also have the following methods:
.. method:: deque.append(x)
Add *x* to the right side of the deque.
Raises IndexError if overflow checking is enabled and there is no more room left.
Raises ``IndexError`` if overflow checking is enabled and there is
no more room in the queue.
.. method:: deque.appendleft(x)
Add *x* to the left side of the deque.
Raises ``IndexError`` if overflow checking is enabled and there is
no more room in the queue.
.. method:: deque.pop()
Remove and return an item from the right side of the deque.
Raises ``IndexError`` if no items are present.
.. method:: deque.popleft()
Remove and return an item from the left side of the deque.
Raises IndexError if no items are present.
Raises ``IndexError`` if no items are present.
.. method:: deque.extend(iterable)
Extend the deque by appending all the items from *iterable* to
the right of the deque.
Raises ``IndexError`` if overflow checking is enabled and there is
no more room in the deque.
.. function:: namedtuple(name, fields)

Wyświetl plik

@ -62,12 +62,35 @@ Functions
.. function:: flash_erase(sector_no)
.. function:: osdebug(level)
.. function:: osdebug(uart_no)
Turn esp os debugging messages on or off.
.. note:: This is the ESP8266 form of this function.
The *level* parameter sets the threshold for the log messages for all esp components.
The log levels are defined as constants:
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
@ -77,6 +100,15 @@ Functions
* ``LOG_VERBOSE`` -- Bigger chunks of debugging information, or frequent messages
which can potentially flood the output
.. note:: ``LOG_DEBUG`` and ``LOG_VERBOSE`` are not compiled into the
MicroPython binary by default, to save size. A custom build with a
modified "``sdkconfig``" source file is needed to see any output
at these log levels.
.. note:: Log output on ESP32 is automatically suspended in "Raw REPL" mode,
to prevent communications issues. This means OS level logging is never
seen when using ``mpremote run`` and similar tools.
.. function:: set_native_code_location(start, length)
**Note**: ESP8266 only

Wyświetl plik

@ -114,7 +114,7 @@ methods to enable over-the-air (OTA) updates.
These methods implement the simple and :ref:`extended
<block-device-interface>` block protocol defined by
:class:`os.AbstractBlockDev`.
:class:`vfs.AbstractBlockDev`.
.. method:: Partition.set_boot()
@ -193,7 +193,7 @@ numbers specified in ``write_pulses`` are multiplied by the resolution to
define the pulses.
``clock_div`` is an 8-bit divider (0-255) and each pulse can be defined by
multiplying the resolution by a 15-bit (0-32,768) number. There are eight
multiplying the resolution by a 15-bit (1-``PULSE_MAX``) number. There are eight
channels (0-7) and each can have a different clock divider.
So, in the example above, the 80MHz clock is divided by 8. Thus the
@ -226,7 +226,7 @@ For more details see Espressif's `ESP-IDF RMT documentation.
``100``) and the output level to apply the carrier to (a boolean as per
*idle_level*).
.. method:: RMT.source_freq()
.. classmethod:: RMT.source_freq()
Returns the source clock frequency. Currently the source clock is not
configurable so this will always return 80MHz.
@ -264,10 +264,10 @@ For more details see Espressif's `ESP-IDF RMT documentation.
**Mode 3:** *duration* and *data* are lists or tuples of equal length,
specifying individual durations and the output level for each.
Durations are in integer units of the channel resolution (as described
above), between 1 and 32767 units. Output levels are any value that can
be converted to a boolean, with ``True`` representing high voltage and
``False`` representing low.
Durations are in integer units of the channel resolution (as
described above), between 1 and ``PULSE_MAX`` units. Output levels
are any value that can be converted to a boolean, with ``True``
representing high voltage and ``False`` representing low.
If transmission of an earlier sequence is in progress then this method will
block until that transmission is complete before beginning the new sequence.
@ -290,6 +290,13 @@ For more details see Espressif's `ESP-IDF RMT documentation.
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
----------------------------

Wyświetl plik

@ -287,7 +287,7 @@ after reboot/reset). This reduces the reliability of receiving ESP-NOW messages
.. method:: ESPNow.irecv([timeout_ms])
Works like `ESPNow.recv()` but will re-use internal bytearrays to store the
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.

Wyświetl plik

@ -103,7 +103,9 @@ the following libraries.
micropython.rst
neopixel.rst
network.rst
openamp.rst
uctypes.rst
vfs.rst
The following libraries provide drivers for hardware components.

Wyświetl plik

@ -86,16 +86,6 @@ Functions
Classes
-------
.. class:: FileIO(...)
This is type of a file open in binary mode, e.g. using ``open(name, "rb")``.
You should not instantiate this class directly.
.. class:: TextIOWrapper(...)
This is type of a file open in text mode, e.g. using ``open(name, "rt")``.
You should not instantiate this class directly.
.. class:: StringIO([string])
.. class:: BytesIO([string])

Wyświetl plik

@ -26,7 +26,7 @@ Constructors
Access the ADC peripheral identified by *id*, which may be an integer
or string.
The *bits* argument, if given, sets the resolution in bits of the
conversion process. If not specified then the previous or default
resolution is used.
@ -39,9 +39,9 @@ Methods
Configure the ADC peripheral. *bits* will set the resolution of the
conversion process.
.. method:: ADCBlock.connect(channel)
ADCBlock.connect(source)
ADCBlock.connect(channel, source)
.. method:: ADCBlock.connect(channel, *, ...)
ADCBlock.connect(source, *, ...)
ADCBlock.connect(channel, source, *, ...)
Connect up a channel on the ADC peripheral so it is ready for sampling,
and return an :ref:`ADC <machine.ADC>` object that represents that connection.
@ -56,3 +56,6 @@ Methods
If both *channel* and *source* are given then they are connected together
and made ready for sampling.
Any additional keyword arguments are used to configure the returned ADC object,
via its :meth:`init <machine.ADC.init>` method.

Wyświetl plik

@ -86,7 +86,7 @@ Specific PWM class implementations
The following concrete class(es) implement enhancements to the PWM class.
| :ref:`pyb.Timer for PyBoard <pyb.Timer>`
| :ref:`pyb.Timer for PyBoard <pyb.Timer>`
Limitations of PWM
------------------
@ -103,7 +103,7 @@ Limitations of PWM
Some ports like the RP2040 one use a fractional divider, which allow a finer
granularity of the frequency at higher frequencies by switching the PWM
pulse duration between two adjacent values, such that the resulting average
frequency is more close to the intended one, at the cost of spectral purity.
frequency is more close to the intended one, at the cost of spectral purity.
* The duty cycle has the same discrete nature and its absolute accuracy is not
achievable. On most hardware platforms the duty will be applied at the next

Wyświetl plik

@ -20,11 +20,11 @@ more info regarding the pins which can be remapped to be used with a SD card.
Example usage::
from machine import SD
import os
import vfs
# clk cmd and dat0 pins must be passed along with
# their respective alternate functions
sd = machine.SD(pins=('GP10', 'GP11', 'GP15'))
os.mount(sd, '/sd')
vfs.mount(sd, '/sd')
# do normal file operations
Constructors

Wyświetl plik

@ -27,10 +27,10 @@ vary from platform to platform.
This class provides access to SD or MMC storage cards using either
a dedicated SD/MMC interface hardware or through an SPI channel.
The class implements the block protocol defined by :class:`os.AbstractBlockDev`.
The class implements the block protocol defined by :class:`vfs.AbstractBlockDev`.
This allows the mounting of an SD card to be as simple as::
os.mount(machine.SDCard(), "/sd")
vfs.mount(machine.SDCard(), "/sd")
The constructor takes the following parameters:

Wyświetl plik

@ -0,0 +1,286 @@
.. currentmodule:: machine
.. _machine.USBDevice:
class USBDevice -- USB Device driver
====================================
.. note:: ``machine.USBDevice`` is currently only supported on the rp2 and samd
ports.
USBDevice provides a low-level Python API for implementing USB device functions using
Python code. This low-level API assumes familiarity with the USB standard. It's
not recommended to use this API directly, instead install the high-level usbd
module from micropython-lib.
.. warning:: This functionality is very new and the high-level usbd module is
not yet merged into micropython-lib. It can be found `here on
GitHub <https://github.com/micropython/micropython-lib/pull/558>`_.
Terminology
-----------
- A "Runtime" USB device interface or driver is one which is defined using this
Python API after MicroPython initially starts up.
- A "Built-in" USB device interface or driver is one that is compiled into the
MicroPython firmware, and is always available. Examples are USB-CDC (serial
port) which is usually enabled by default. Built-in USB-MSC (Mass Storage) is an
option on some ports.
Lifecycle
---------
Managing a runtime USB interface can be tricky, especially if you are communicating
with MicroPython over a built-in USB-CDC serial port that's part of the same USB
device.
- A MicroPython soft reset will always clear all runtime USB interfaces, which
results in the entire USB device disconnecting from the host. If MicroPython
is also providing a built-in USB-CDC serial port then this will re-appear
after the soft reset.
This means some functions (like ``mpremote run``) that target the USB-CDC
serial port will immediately fail if a runtime USB interface is active,
because the port goes away when ``mpremote`` triggers a soft reset. The
operation should succeed on the second try, as after the soft reset there is
no more runtime USB interface.
- To configure a runtime USB device on every boot, it's recommended to place the
configuration code in the ``boot.py`` file on the :ref:`device VFS
<filesystem>`. On each reset this file is executed before the USB subsystem is
initialised (and before ``main.py``), so it allows the board to come up with the runtime
USB device immediately.
- For development or debugging, it may be convenient to connect a hardware
serial REPL and disable the built-in USB-CDC serial port entirely. Not all ports
support this (currently only ``rp2``). The custom build should be configured
with ``#define MICROPY_HW_USB_CDC (0)`` and ``#define
MICROPY_HW_ENABLE_UART_REPL (1)``.
Constructors
------------
.. class:: USBDevice()
Construct a USBDevice object.
.. note:: This object is a singleton, each call to this constructor
returns the same object reference.
Methods
-------
.. method:: USBDevice.config(desc_dev, desc_cfg, desc_strs=None, open_itf_cb=None, reset_cb=None, control_xfer_cb=None, xfer_cb=None)
Configures the ``USBDevice`` singleton object with the USB runtime device
state and callback functions:
- ``desc_dev`` - A bytes-like object containing
the new USB device descriptor.
- ``desc_cfg`` - A bytes-like object containing the
new USB configuration descriptor.
- ``desc_strs`` - Optional object holding strings or bytes objects
containing USB string descriptor values. Can be a list, a dict, or any
object which supports subscript indexing with integer keys (USB string
descriptor index).
Strings are an optional USB feature, and this parameter can be unset
(default) if no strings are referenced in the device and configuration
descriptors, or if only built-in strings should be used.
Apart from index 0, all the string values should be plain ASCII. Index 0
is the special "languages" USB descriptor, represented as a bytes object
with a custom format defined in the USB standard. ``None`` can be
returned at index 0 in order to use a default "English" language
descriptor.
To fall back to providing a built-in string value for a given index, a
subscript lookup can return ``None``, raise ``KeyError``, or raise
``IndexError``.
- ``open_itf_cb`` - This callback is called once for each interface
or Interface Association Descriptor in response to a Set
Configuration request from the USB Host (the final stage before
the USB device is available to the host).
The callback takes a single argument, which is a memoryview of the
interface or IAD descriptor that the host is accepting (including
all associated descriptors). It is a view into the same
``desc_cfg`` object that was provided as a separate
argument to this function. The memoryview is only valid until the
callback function returns.
- ``reset_cb`` - This callback is called when the USB host performs
a bus reset. The callback takes no arguments. Any in-progress
transfers will never complete. The USB host will most likely
proceed to re-enumerate the USB device by calling the descriptor
callbacks and then ``open_itf_cb()``.
- ``control_xfer_cb`` - This callback is called one or more times
for each USB control transfer (device Endpoint 0). It takes two
arguments.
The first argument is the control transfer stage. It is one of:
- ``1`` for SETUP stage.
- ``2`` for DATA stage.
- ``3`` for ACK stage.
Second argument is a memoryview to read the USB control request
data for this stage. The memoryview is only valid until the
callback function returns.
The callback should return one of the following values:
- ``False`` to stall the endpoint and reject the transfer.
- ``True`` to continue the transfer to the next stage.
- A buffer object to provide data for this stage of the transfer.
This should be a writable buffer for an ``OUT`` direction transfer, or a
readable buffer with data for an ``IN`` direction transfer.
- ``xfer_cb`` - This callback is called whenever a non-control
transfer submitted by calling :func:`USBDevice.submit_xfer` completes.
The callback has three arguments:
1. The Endpoint number for the completed transfer.
2. Result value: ``True`` if the transfer succeeded, ``False``
otherwise.
3. Number of bytes successfully transferred. In the case of a
"short" transfer, The result is ``True`` and ``xferred_bytes``
will be smaller than the length of the buffer submitted for the
transfer.
.. note:: If a bus reset occurs (see :func:`USBDevice.reset`),
``xfer_cb`` is not called for any transfers that have not
already completed.
.. method:: USBDevice.active(self, [value] /)
Returns the current active state of this runtime USB device as a
boolean. The runtime USB device is "active" when it is available to
interact with the host, it doesn't mean that a USB Host is actually
present.
If the optional ``value`` argument is set to a truthy value, then
the USB device will be activated.
If the optional ``value`` argument is set to a falsey value, then
the USB device is deactivated. While the USB device is deactivated,
it will not be detected by the USB Host.
To simulate a disconnect and a reconnect of the USB device, call
``active(False)`` followed by ``active(True)``. This may be
necessary if the runtime device configuration has changed, so that
the host sees the new device.
.. attribute:: USDBD.builtin_driver
This attribute holds the current built-in driver configuration, and must be
set to one of the ``USBDevice.BUILTIN_`` named constants defined on this object.
By default it holds the value :data:`USBDevice.BUILTIN_NONE`.
Runtime USB device must be inactive when setting this field. Call the
:func:`USBDevice.active` function to deactivate before setting if necessary
(and again to activate after setting).
If this value is set to any value other than :data:`USBDevice.BUILTIN_NONE` then
the following restrictions apply to the :func:`USBDevice.config` arguments:
- ``desc_cfg`` should begin with the built-in USB interface descriptor data
accessible via :data:`USBDevice.builtin_driver` attribute ``desc_cfg``.
Descriptors appended after the built-in configuration descriptors should use
interface, string and endpoint numbers starting from the max built-in values
defined in :data:`USBDevice.builtin_driver` attributes ``itf_max``, ``str_max`` and
``ep_max``.
- The ``bNumInterfaces`` field in the built-in configuration
descriptor will also need to be updated if any new interfaces
are appended to the end of ``desc_cfg``.
- ``desc_strs`` should either be ``None`` or a list/dictionary where index
values less than ``USBDevice.builtin_driver.str_max`` are missing or have
value ``None``. This reserves those string indexes for the built-in
drivers. Placing a different string at any of these indexes overrides that
string in the built-in driver.
.. method:: USBDevice.submit_xfer(self, ep, buffer /)
Submit a USB transfer on endpoint number ``ep``. ``buffer`` must be
an object implementing the buffer interface, with read access for
``IN`` endpoints and write access for ``OUT`` endpoints.
.. note:: ``ep`` cannot be the control Endpoint number 0. Control
transfers are built up through successive executions of
``control_xfer_cb``, see above.
Returns ``True`` if successful, ``False`` if the transfer could not
be queued (as USB device is not configured by host, or because
another transfer is queued on this endpoint.)
When the USB host completes the transfer, the ``xfer_cb`` callback
is called (see above).
Raises ``OSError`` with reason ``MP_EINVAL`` If the USB device is not
active.
.. method:: USBDevice.stall(self, ep, [stall] /)
Calling this function gets or sets the STALL state of a device endpoint.
``ep`` is the number of the endpoint.
If the optional ``stall`` parameter is set, this is a boolean flag
for the STALL state.
The return value is the current stall state of the endpoint (before
any change made by this function).
An endpoint that is set to STALL may remain stalled until this
function is called again, or STALL may be cleared automatically by
the USB host.
Raises ``OSError`` with reason ``MP_EINVAL`` If the USB device is not
active.
Constants
---------
.. data:: USBDevice.BUILTIN_NONE
.. data:: USBDevice.BUILTIN_DEFAULT
.. data:: USBDevice.BUILTIN_CDC
.. data:: USBDevice.BUILTIN_MSC
.. data:: USBDevice.BUILTIN_CDC_MSC
These constant objects hold the built-in descriptor data which is
compiled into the MicroPython firmware. ``USBDevice.BUILTIN_NONE`` and
``USBDevice.BUILTIN_DEFAULT`` are always present. Additional objects may be present
depending on the firmware build configuration and the actual built-in drivers.
.. note:: Currently at most one of ``USBDevice.BUILTIN_CDC``,
``USBDevice.BUILTIN_MSC`` and ``USBDevice.BUILTIN_CDC_MSC`` is defined
and will be the same object as ``USBDevice.BUILTIN_DEFAULT``.
These constants are defined to allow run-time detection of
the built-in driver (if any). Support for selecting one of
multiple built-in driver configurations may be added in the
future.
These values are assigned to :data:`USBDevice.builtin_driver` to get/set the
built-in configuration.
Each object contains the following read-only fields:
- ``itf_max`` - One more than the highest bInterfaceNumber value used
in the built-in configuration descriptor.
- ``ep_max`` - One more than the highest bEndpointAddress value used
in the built-in configuration descriptor. Does not include any
``IN`` flag bit (0x80).
- ``str_max`` - One more than the highest string descriptor index
value used by any built-in descriptor.
- ``desc_dev`` - ``bytes`` object containing the built-in USB device
descriptor.
- ``desc_cfg`` - ``bytes`` object containing the complete built-in USB
configuration descriptor.

Wyświetl plik

@ -265,3 +265,4 @@ Classes
machine.WDT.rst
machine.SD.rst
machine.SDCard.rst
machine.USBDevice.rst

Wyświetl plik

@ -188,6 +188,11 @@ The following are functions available in the network module.
during connection. For this reason, you must set the hostname before
activating/connecting your network interfaces.
The length of the hostname is limited to 32 characters.
:term:`MicroPython ports <MicroPython port>` may choose to set a lower
limit for memory reasons. If the given name does not fit, a `ValueError`
is raised.
The default hostname is typically the name of the board.
.. function:: phy_mode([mode])

Wyświetl plik

@ -0,0 +1,115 @@
:mod:`openamp` -- provides standard Asymmetric Multiprocessing (AMP) support
============================================================================
.. module:: openamp
:synopsis: provides standard Asymmetric Multiprocessing (AMP) support
The ``openamp`` module provides a standard inter-processor communications infrastructure
for MicroPython. The module handles all of the details of OpenAMP, such as setting up
the shared resource table, initializing vrings, etc. It provides an API for using the
RPMsg bus infrastructure with the `Endpoint` class, and provides processor Life Cycle
Management (LCM) support, such as loading firmware and starting and stopping a remote
core, via the `RemoteProc` class.
Example usage::
import openamp
def ept_recv_callback(src, data):
print("Received message on endpoint", data)
# Create a new RPMsg endpoint to communicate with the remote core.
ept = openamp.Endpoint("vuart-channel", callback=ept_recv_callback)
# Create a RemoteProc object, load its firmware and start it.
rproc = openamp.RemoteProc("virtual_uart.elf") # Or entry point address (ex 0x081E0000)
rproc.start()
while True:
if ept.is_ready():
ept.send("data")
Functions
---------
.. function:: new_service_callback(ns_callback)
Set the new service callback.
The *ns_callback* argument is a function that will be called when the remote processor
announces new services. At that point the host processor can choose to create the
announced endpoint, if this particular service is supported, or ignore it if it's
not. If this function is not set, the host processor should first register the
endpoint locally, and it will be automatically bound when the remote announces
the service.
Endpoint class
--------------
.. class:: Endpoint(name, callback, src=ENDPOINT_ADDR_ANY, dest=ENDPOINT_ADDR_ANY)
Construct a new RPMsg Endpoint. An endpoint is a bidirectional communication
channel between two cores.
Arguments are:
- *name* is the name of the endpoint.
- *callback* is a function that is called when the endpoint receives data with the
source address of the remote point, and the data as bytes passed by reference.
- *src* is the endpoint source address. If none is provided one will be assigned
to the endpoint by the library.
- *dest* is the endpoint destination address. If the endpoint is created from the
new_service_callback, this must be provided and it must match the remote endpoint's
source address. If the endpoint is registered locally, before the announcement, the
destination address will be assigned by the library when the endpoint is bound.
.. method:: Endpoint.deinit()
Destroy the endpoint and release all of its resources.
.. method:: Endpoint.is_ready()
Returns True if the endpoint is ready to send (i.e., has both a source and destination addresses)
.. method:: Endpoint.send(src=-1, dest=-1, timeout=-1)
Send a message to the remote processor over this endpoint.
Arguments are:
- *src* is the source endpoint address of the message. If none is provided, the
source address the endpoint is bound to is used.
- *dest* is the destination endpoint address of the message. If none is provided,
the destination address the endpoint is bound to is used.
- *timeout* specifies the time in milliseconds to wait for a free buffer. By default
the function is blocking.
RemoteProc class
----------------
.. class:: RemoteProc(entry)
The RemoteProc object provides processor Life Cycle Management (LCM) support, such as
loading firmware, starting and stopping a remote core.
The *entry* argument can be a path to firmware image, in which case the firmware is
loaded from file to its target memory, or an entry point address, in which case the
firmware must be loaded already at the given address.
.. method:: RemoteProc.start()
Starts the remote processor.
.. method:: RemoteProc.stop()
Stops the remote processor. The exact behavior is platform-dependent. On the STM32H7 for
example it's not possible to stop and then restart the Cortex-M4 core, so a complete
system reset is performed on a call to this function.
.. method:: RemoteProc.shutdown()
Shutdown stops the remote processor and releases all of its resources. The exact behavior
is platform-dependent, however typically it disables power and clocks to the remote core.
This function is also used as the finaliser (i.e., called when ``RemoteProc`` object is
collected). Note that on the STM32H7, it's not possible to stop and then restart the
Cortex-M4 core, so a complete system reset is performed on a call to this function.

Wyświetl plik

@ -136,192 +136,30 @@ Terminal redirection and duplication
Filesystem mounting
-------------------
Some ports provide a Virtual Filesystem (VFS) and the ability to mount multiple
"real" filesystems within this VFS. Filesystem objects can be mounted at either
the root of the VFS, or at a subdirectory that lives in the root. This allows
dynamic and flexible configuration of the filesystem that is seen by Python
programs. Ports that have this functionality provide the :func:`mount` and
:func:`umount` functions, and possibly various filesystem implementations
represented by VFS classes.
The following functions and classes have been moved to the :mod:`vfs` module.
They are provided in this module only for backwards compatibility and will be
removed in version 2 of MicroPython.
.. function:: mount(fsobj, mount_point, *, readonly)
Mount the filesystem object *fsobj* at the location in the VFS given by the
*mount_point* string. *fsobj* can be a a VFS object that has a ``mount()``
method, or a block device. If it's a block device then the filesystem type
is automatically detected (an exception is raised if no filesystem was
recognised). *mount_point* may be ``'/'`` to mount *fsobj* at the root,
or ``'/<name>'`` to mount it at a subdirectory under the root.
If *readonly* is ``True`` then the filesystem is mounted read-only.
During the mount process the method ``mount()`` is called on the filesystem
object.
Will raise ``OSError(EPERM)`` if *mount_point* is already mounted.
See `vfs.mount`.
.. function:: umount(mount_point)
Unmount a filesystem. *mount_point* can be a string naming the mount location,
or a previously-mounted filesystem object. During the unmount process the
method ``umount()`` is called on the filesystem object.
Will raise ``OSError(EINVAL)`` if *mount_point* is not found.
See `vfs.umount`.
.. class:: VfsFat(block_dev)
Create a filesystem object that uses the FAT filesystem format. Storage of
the FAT filesystem is provided by *block_dev*.
Objects created by this constructor can be mounted using :func:`mount`.
.. staticmethod:: mkfs(block_dev)
Build a FAT filesystem on *block_dev*.
See `vfs.VfsFat`.
.. class:: VfsLfs1(block_dev, readsize=32, progsize=32, lookahead=32)
Create a filesystem object that uses the `littlefs v1 filesystem format`_.
Storage of the littlefs filesystem is provided by *block_dev*, which must
support the :ref:`extended interface <block-device-interface>`.
Objects created by this constructor can be mounted using :func:`mount`.
See :ref:`filesystem` for more information.
.. staticmethod:: mkfs(block_dev, readsize=32, progsize=32, lookahead=32)
Build a Lfs1 filesystem on *block_dev*.
.. note:: There are reports of littlefs v1 failing in certain situations,
for details see `littlefs issue 347`_.
See `vfs.VfsLfs1`.
.. class:: VfsLfs2(block_dev, readsize=32, progsize=32, lookahead=32, mtime=True)
Create a filesystem object that uses the `littlefs v2 filesystem format`_.
Storage of the littlefs filesystem is provided by *block_dev*, which must
support the :ref:`extended interface <block-device-interface>`.
Objects created by this constructor can be mounted using :func:`mount`.
See `vfs.VfsLfs2`.
The *mtime* argument enables modification timestamps for files, stored using
littlefs attributes. This option can be disabled or enabled differently each
mount time and timestamps will only be added or updated if *mtime* is enabled,
otherwise the timestamps will remain untouched. Littlefs v2 filesystems without
timestamps will work without reformatting and timestamps will be added
transparently to existing files once they are opened for writing. When *mtime*
is enabled `os.stat` on files without timestamps will return 0 for the timestamp.
.. class:: VfsPosix(root=None)
See :ref:`filesystem` for more information.
.. staticmethod:: mkfs(block_dev, readsize=32, progsize=32, lookahead=32)
Build a Lfs2 filesystem on *block_dev*.
.. note:: There are reports of littlefs v2 failing in certain situations,
for details see `littlefs issue 295`_.
.. _littlefs v1 filesystem format: https://github.com/ARMmbed/littlefs/tree/v1
.. _littlefs v2 filesystem format: https://github.com/ARMmbed/littlefs
.. _littlefs issue 295: https://github.com/ARMmbed/littlefs/issues/295
.. _littlefs issue 347: https://github.com/ARMmbed/littlefs/issues/347
Block devices
-------------
A block device is an object which implements the block protocol. This enables a
device to support MicroPython filesystems. The physical hardware is represented
by a user defined class. The :class:`AbstractBlockDev` class is a template for
the design of such a class: MicroPython does not actually provide that class,
but an actual block device class must implement the methods described below.
A concrete implementation of this class will usually allow access to the
memory-like functionality of a piece of hardware (like flash memory). A block
device can be formatted to any supported filesystem and mounted using ``os``
methods.
See :ref:`filesystem` for example implementations of block devices using the
two variants of the block protocol described below.
.. _block-device-interface:
Simple and extended interface
.............................
There are two compatible signatures for the ``readblocks`` and ``writeblocks``
methods (see below), in order to support a variety of use cases. A given block
device may implement one form or the other, or both at the same time. The second
form (with the offset parameter) is referred to as the "extended interface".
Some filesystems (such as littlefs) that require more control over write
operations, for example writing to sub-block regions without erasing, may require
that the block device supports the extended interface.
.. class:: AbstractBlockDev(...)
Construct a block device object. The parameters to the constructor are
dependent on the specific block device.
.. method:: readblocks(block_num, buf)
readblocks(block_num, buf, offset)
The first form reads aligned, multiples of blocks.
Starting at the block given by the index *block_num*, read blocks from
the device into *buf* (an array of bytes).
The number of blocks to read is given by the length of *buf*,
which will be a multiple of the block size.
The second form allows reading at arbitrary locations within a block,
and arbitrary lengths.
Starting at block index *block_num*, and byte offset within that block
of *offset*, read bytes from the device into *buf* (an array of bytes).
The number of bytes to read is given by the length of *buf*.
.. method:: writeblocks(block_num, buf)
writeblocks(block_num, buf, offset)
The first form writes aligned, multiples of blocks, and requires that the
blocks that are written to be first erased (if necessary) by this method.
Starting at the block given by the index *block_num*, write blocks from
*buf* (an array of bytes) to the device.
The number of blocks to write is given by the length of *buf*,
which will be a multiple of the block size.
The second form allows writing at arbitrary locations within a block,
and arbitrary lengths. Only the bytes being written should be changed,
and the caller of this method must ensure that the relevant blocks are
erased via a prior ``ioctl`` call.
Starting at block index *block_num*, and byte offset within that block
of *offset*, write bytes from *buf* (an array of bytes) to the device.
The number of bytes to write is given by the length of *buf*.
Note that implementations must never implicitly erase blocks if the offset
argument is specified, even if it is zero.
.. method:: ioctl(op, arg)
Control the block device and query its parameters. The operation to
perform is given by *op* which is one of the following integers:
- 1 -- initialise the device (*arg* is unused)
- 2 -- shutdown the device (*arg* is unused)
- 3 -- sync the device (*arg* is unused)
- 4 -- get a count of the number of blocks, should return an integer
(*arg* is unused)
- 5 -- get the number of bytes in a block, should return an integer,
or ``None`` in which case the default value of 512 is used
(*arg* is unused)
- 6 -- erase a block, *arg* is the block number to erase
As a minimum ``ioctl(4, ...)`` must be intercepted; for littlefs
``ioctl(6, ...)`` must also be intercepted. The need for others is
hardware dependent.
Prior to any call to ``writeblocks(block, ...)`` littlefs issues
``ioctl(6, block)``. This enables a device driver to erase the block
prior to a write if the hardware requires it. Alternatively a driver
might intercept ``ioctl(6, block)`` and return 0 (success). In this case
the driver assumes responsibility for detecting the need for erasure.
Unless otherwise stated ``ioctl(op, arg)`` can return ``None``.
Consequently an implementation can ignore unused values of ``op``. Where
``op`` is intercepted, the return value for operations 4 and 5 are as
detailed above. Other operations should return 0 on success and non-zero
for failure, with the value returned being an ``OSError`` errno code.
See `vfs.VfsPosix`.

Wyświetl plik

@ -43,7 +43,7 @@ Methods
These methods implement the simple and :ref:`extended
<block-device-interface>` block protocol defined by
:class:`os.AbstractBlockDev`.
:class:`vfs.AbstractBlockDev`.
Hardware Note
-------------

Wyświetl plik

@ -213,11 +213,11 @@ Miscellaneous functions
.. function:: mount(device, mountpoint, *, readonly=False, mkfs=False)
.. note:: This function is deprecated. Mounting and unmounting devices should
be performed by :meth:`os.mount` and :meth:`os.umount` instead.
be performed by :meth:`vfs.mount` and :meth:`vfs.umount` instead.
Mount a block device and make it available as part of the filesystem.
``device`` must be an object that provides the block protocol. (The
following is also deprecated. See :class:`os.AbstractBlockDev` for the
following is also deprecated. See :class:`vfs.AbstractBlockDev` for the
correct way to create a block device.)
- ``readblocks(self, blocknum, buf)``

Wyświetl plik

@ -0,0 +1,293 @@
.. currentmodule:: rp2
.. _rp2.DMA:
class DMA -- access to the RP2040's DMA controller
==================================================
The :class:`DMA` class offers access to the RP2040's Direct Memory Access (DMA)
controller, providing the ability move data between memory blocks and/or IO registers. The DMA
controller has its own, separate read and write bus master connections onto the bus fabric and
each DMA channel can independently read data from one address and write it back to another
address, optionally incrementing one or both pointers, allowing it to perform transfers on behalf
of the processor while the processor carries out other tasks or enters a low power state. The
RP2040's DMA controller has 12 independent DMA channels that can run concurrently. For full
details of the RP2040's DMA system see section 2.5 of the `RP2040 Datasheet
<https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf>`_.
Examples
--------
The simplest use of the DMA controller is to move data from one block of memory to another.
This can be accomplished with the following code::
a = bytearray(32*1024)
b = bytearray(32*1024)
d = rp2.DMA()
c = d.pack_ctrl() # Just use the default control value.
# The count is in 'transfers', which defaults to four-byte words, so divide length by 4
d.config(read=a, write=b, count=len(a)//4, ctrl=c, trigger=True)
# Wait for completion
while d.active():
pass
Note that while this example sits in an idle loop while it waits for the transfer to complete,
the program could just as well do some useful work in this time instead.
Another, perhaps more common use of the DMA controller is to transfer between memory and an IO
peripheral. In this situation the address of the IO register does not change for each transfer but
the memory address needs to be incremented. It is also necessary to control the pace of the
transfer so as to not write data before it can be accepted by a peripheral or read it before the
data is ready, and this can be controlled with the ``treq_sel`` field of the DMA channel's control
register. The various fields of the control register for each DMA channel can be packed
using the :meth:`DMA.pack_ctrl()` method and unpacked using the :meth:`DMA.unpack_ctrl()`
static method. Code to transfer data from a byte array to the TX FIFO of a PIO state machine,
one byte at a time, looks like this::
# pio_num is index of the PIO block being used, sm_num is the state machine in that block.
# my_state_machine is an rp2.PIO() instance.
DATA_REQUEST_INDEX = (pio_num << 3) + sm_num
src_data = bytearray(1024)
d = rp2.DMA()
# Transfer bytes, rather than words, don't increment the write address and pace the transfer.
c = d.pack_ctrl(size=0, inc_write=False, treq_sel=DATA_REQUEST_INDEX)
d.config(
read=src_data,
write=my_state_machine,
count=len(src_data),
ctrl=c,
trigger=True
)
Note that in this example the value given for the write address is just the PIO state machine to
which we are sending the data. This works because PIO state machines present the buffer protocol,
allowing direct access to their data FIFO registers.
Constructor
-----------
.. class:: DMA()
Claim one of the DMA controller channels for exclusive use.
Methods
-------
.. method:: DMA.config(read=None, write=None, count=None, ctrl=None, trigger=False)
Configure the DMA registers for the channel and optionally start the transfer.
Parameters are:
- *read*: The address from which the DMA controller will start reading data or
an object that will provide data to be read. It can be an integer or any
object that supports the buffer protocol.
- *write*: The address to which the DMA controller will start writing or an
object into which data will be written. It can be an integer or any object
that supports the buffer protocol.
- *count*: The number of bus transfers that will execute before this channel
stops. Note that this is the number of transfers, not the number of bytes.
If the transfers are 2 or 4 bytes wide then the total amount of data moved
(and thus the size of required buffer) needs to be multiplied accordingly.
- *ctrl*: The value for the DMA control register. This is an integer value
that is typically packed using the :meth:`DMA.pack_ctrl()`.
- *trigger*: Optionally commence the transfer immediately.
.. method:: DMA.irq(handler=None, hard=False)
Returns the IRQ object for this DMA channel and optionally configures it.
.. method:: DMA.close()
Release the claim on the underlying DMA channel and free the interrupt
handler. The :class:`DMA` object can not be used after this operation.
.. method:: DMA.pack_ctrl(default=None, **kwargs)
Pack the values provided in the keyword arguments into the named fields of a new control
register value. Any field that is not provided will be set to a default value. The
default will either be taken from the provided ``default`` value, or if that is not
given, a default suitable for the current channel; setting this to the current value
of the `DMA.ctrl` attribute provides an easy way to override a subset of the fields.
The keys for the keyword arguments can be any key returned by the :meth:`DMA.unpack_ctrl()`
method. The writable values are:
- *enable*: ``bool`` Set to enable the channel (default: ``True``).
- *high_pri*: ``bool`` Make this channel's bus traffic high priority (default: ``False``).
- *size*: ``int`` Transfer size: 0=byte, 1=half word, 2=word (default: 2).
- *inc_read*: ``bool`` Increment the read address after each transfer (default: ``True``).
- *inc_write*: ``bool`` Increment the write address after each transfer (default: ``True``).
- *ring_size*: ``int`` If non-zero, only the bottom ``ring_size`` bits of one
address register will change when an address is incremented, causing the
address to wrap at the next ``1 << ring_size`` byte boundary. Which
address is wrapped is controlled by the ``ring_sel`` flag. A zero value
disables address wrapping.
- *ring_sel*: ``bool`` Set to ``False`` to have the ``ring_size`` apply to the read address
or ``True`` to apply to the write address.
- *chain_to*: ``int`` The channel number for a channel to trigger after this transfer
completes. Setting this value to this DMA object's own channel number
disables chaining (this is the default).
- *treq_sel*: ``int`` Select a Transfer Request signal. See section 2.5.3 in the RP2040
datasheet for details.
- *irq_quiet*: ``bool`` Do not generate interrupt at the end of each transfer. Interrupts
will instead be generated when a zero value is written to the trigger
register, which will halt a sequence of chained transfers (default:
``True``).
- *bswap*: ``bool`` If set to true, bytes in words or half-words will be reversed before
writing (default: ``True``).
- *sniff_en*: ``bool`` Set to ``True`` to allow data to be accessed by the chips sniff
hardware (default: ``False``).
- *write_err*: ``bool`` Setting this to ``True`` will clear a previously reported write
error.
- *read_err*: ``bool`` Setting this to ``True`` will clear a previously reported read
error.
See the description of the ``CH0_CTRL_TRIG`` register in section 2.5.7 of the RP2040
datasheet for details of all of these fields.
.. method:: DMA.unpack_ctrl(value)
Unpack a value for a DMA channel control register into a dictionary with key/value pairs
for each of the fields in the control register. *value* is the ``ctrl`` register value
to unpack.
This method will return values for all the keys that can be passed to ``DMA.pack_ctrl``.
In addition, it will also return the read-only flags in the control register: ``busy``,
which goes high when a transfer starts and low when it ends, and ``ahb_err``, which is
the logical OR of the ``read_err`` and ``write_err`` flags. These values will be ignored
when packing, so that the dictionary created by unpacking a control register can be used
directly as the keyword arguments for packing.
.. method:: DMA.active([value])
Gets or sets whether the DMA channel is currently running.
>>> sm.active()
0
>>> sm.active(1)
>>> while sm.active():
... pass
Attributes
----------
.. attribute:: DMA.read
This attribute reflects the address from which the next bus transfer
will read. It may be written with either an integer or an object
that supports the buffer protocol and doing so has immediate effect.
.. attribute:: DMA.write
This attribute reflects the address to which the next bus transfer
will write. It may be written with either an integer or an object
that supports the buffer protocol and doing so has immediate effect.
.. attribute:: DMA.count
Reading this attribute will return the number of remaining bus
transfers in the *current* transfer sequence. Writing this attribute
sets the total number of transfers to be the *next* transfer sequence.
.. attribute:: DMA.ctrl
This attribute reflects DMA channel control register. It is typically written
with an integer packed using the :meth:`DMA.pack_ctrl()` method. The returned
register value can be unpacked using the :meth:`DMA.unpack_ctrl()` method.
.. attribute:: DMA.channel
The channel number of the DMA channel. This can be passed in the ``chain_to``
argument of `DMA.pack_ctrl()` on another channel to allow DMA chaining.
.. attribute:: DMA.registers
This attribute is an array-like object that allows direct access to
the DMA channel's registers. The index is by word, rather than by byte,
so the register indices are the register address offsets divided by 4.
See the RP2040 data sheet for register details.
Chaining and trigger register access
------------------------------------
The DMA controller in the RP2040 offers a couple advanced features to allow one DMA channel
to initiate a transfer on another channel. One is the use of the ``chain_to`` value in the
control register and the other is writing to one of the DMA channel's registers that has a
trigger effect. When coupled with the ability to have one DMA channel write directly to the
`DMA.registers` of another channel, this allows for complex transactions to be performed
without any CPU intervention.
Below is an example of using both chaining and register
triggering to implement gathering of multiple blocks of data into a single destination. Full
details of these features can be found in section 2.5 of the RP2040 data sheet and the code
below is a Pythonic version of the example in sub-section 2.5.6.2.
.. code-block:: python
from rp2 import DMA
from uctypes import addressof
from array import array
def gather_strings(string_list, buf):
# We use two DMA channels. The first sends lengths and source addresses from the gather
# list to the registers of the second. The second copies the data itself.
gather_dma = DMA()
buffer_dma = DMA()
# Pack up length/address pairs to be sent to the registers.
gather_list = array("I")
for s in string_list:
gather_list.append(len(s))
gather_list.append(addressof(s))
gather_list.append(0)
gather_list.append(0)
# When writing to the registers of the second DMA channel, we need to wrap the
# write address on an 8-byte (1<<3 bytes) boundary. We write to the ``TRANS_COUNT``
# and ``READ_ADD_TRIG`` registers in the last register alias (registers 14 and 15).
gather_ctrl = gather_dma.pack_ctrl(ring_size=3, ring_sel=True)
gather_dma.config(
read=gather_list, write=buffer_dma.registers[14:16],
count=2, ctrl=gather_ctrl
)
# When copying the data, the transfer size is single bytes, and when completed we need
# to chain back to the start another gather DMA transaction.
buffer_ctrl = buffer_dma.pack_ctrl(size=0, chain_to=gather_dma.channel)
# The read and count values will be set by the other DMA channel.
buffer_dma.config(write=buf, ctrl=buffer_ctrl)
# Set the transfer in motion.
gather_dma.active(1)
# Wait until all the register values have been sent
end_address = addressof(gather_list) + 4 * len(gather_list)
while gather_dma.read != end_address:
pass
input = ["This is ", "a ", "test", " of the scatter", " gather", " process"]
output = bytearray(64)
print(output)
gather_strings(input, output)
print(output)
This example idles while waiting for the transfer to complete; alternatively it could
set an interrupt handler and return immediately.

Wyświetl plik

@ -32,5 +32,5 @@ Methods
These methods implement the simple and extended
:ref:`block protocol <block-device-interface>` defined by
:class:`os.AbstractBlockDev`.
:class:`vfs.AbstractBlockDev`.

Wyświetl plik

@ -32,7 +32,7 @@ Methods
The program is added to the instruction memory of this PIO instance. If the
instruction memory already contains this program, then its offset is
re-used so as to save on instruction memory.
reused so as to save on instruction memory.
- *freq* is the frequency in Hz to run the state machine at. Defaults to
the system clock frequency.
@ -140,3 +140,10 @@ Methods
Optionally configure it.
Buffer protocol
---------------
The StateMachine class supports the `buffer protocol`, allowing direct access to the transmit
and receive FIFOs for each state machine. This is primarily in order to allow StateMachine
objects to be passed directly as the read or write parameters when configuring a `rp2.DMA()`
channel.

Wyświetl plik

@ -241,6 +241,7 @@ Classes
.. toctree::
:maxdepth: 1
rp2.DMA.rst
rp2.Flash.rst
rp2.PIO.rst
rp2.StateMachine.rst

Wyświetl plik

@ -13,7 +13,7 @@ facilities for network sockets, both client-side and server-side.
Functions
---------
.. function:: ssl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, cadata=None, server_hostname=None, do_handshake=True)
.. function:: ssl.wrap_socket(sock, server_side=False, key=None, cert=None, cert_reqs=CERT_NONE, cadata=None, server_hostname=None, do_handshake=True)
Wrap the given *sock* and return a new wrapped-socket object. The implementation
of this function is to first create an `SSLContext` and then call the `SSLContext.wrap_socket`
@ -39,6 +39,33 @@ class SSLContext
Create a new SSLContext instance. The *protocol* argument must be one of the ``PROTOCOL_*``
constants.
.. method:: SSLContext.load_cert_chain(certfile, keyfile)
Load a private key and the corresponding certificate. The *certfile* is a string
with the file path of the certificate. The *keyfile* is a string with the file path
of the private key.
.. admonition:: Difference to CPython
:class: attention
MicroPython extension: *certfile* and *keyfile* can be bytes objects instead of
strings, in which case they are interpreted as the actual certificate/key data.
.. method:: SSLContext.load_verify_locations(cafile=None, cadata=None)
Load the CA certificate chain that will validate the peer's certificate.
*cafile* is the file path of the CA certificates. *cadata* is a bytes object
containing the CA certificates. Only one of these arguments should be provided.
.. method:: SSLContext.get_ciphers()
Get a list of enabled ciphers, returned as a list of strings.
.. method:: SSLContext.set_ciphers(ciphers)
Set the available ciphers for sockets created with this context. *ciphers* should be
a list of strings in the `IANA cipher suite format <https://wiki.mozilla.org/Security/Cipher_Suites>`_ .
.. method:: SSLContext.wrap_socket(sock, *, server_side=False, do_handshake_on_connect=True, server_hostname=None)
Takes a `stream` *sock* (usually socket.socket instance of ``SOCK_STREAM`` type),
@ -77,6 +104,12 @@ class SSLContext
Set or get the behaviour for verification of peer certificates. Must be one of the
``CERT_*`` constants.
.. note::
``ssl.CERT_REQUIRED`` requires the device's date/time to be properly set, e.g. using
`mpremote rtc --set <mpremote_command_rtc>` or ``ntptime``, and ``server_hostname``
must be specified when on the client side.
Exceptions
----------

Wyświetl plik

@ -45,6 +45,8 @@ The following data types are supported:
+--------+--------------------+-------------------+---------------+
| Q | unsigned long long | integer (`1<fn>`) | 8 |
+--------+--------------------+-------------------+---------------+
| e | n/a (half-float) | float (`2<fn>`) | 2 |
+--------+--------------------+-------------------+---------------+
| f | float | float (`2<fn>`) | 4 |
+--------+--------------------+-------------------+---------------+
| d | double | float (`2<fn>`) | 8 |

Wyświetl plik

@ -69,7 +69,7 @@ Constants
MicroPython, it has following attributes:
* *name* - string "micropython"
* *version* - tuple (major, minor, micro), e.g. (1, 7, 0)
* *version* - tuple (major, minor, micro, releaselevel), e.g. (1, 22, 0, '')
* *_machine* - string describing the underlying machine
* *_mpy* - supported mpy file-format version (optional attribute)
@ -77,6 +77,9 @@ Constants
Python implementations (note that it still may not exist in the very
minimal ports).
Starting with version 1.22.0-preview, the fourth node *releaselevel* in
*implementation.version* is either an empty string or ``"preview"``.
.. admonition:: Difference to CPython
:class: attention

Wyświetl plik

@ -0,0 +1,208 @@
:mod:`vfs` -- virtual filesystem control
========================================
.. module:: vfs
:synopsis: virtual filesystem control
The ``vfs`` module contains functions for creating filesystem objects and
mounting/unmounting them in the Virtual Filesystem.
Filesystem mounting
-------------------
Some ports provide a Virtual Filesystem (VFS) and the ability to mount multiple
"real" filesystems within this VFS. Filesystem objects can be mounted at either
the root of the VFS, or at a subdirectory that lives in the root. This allows
dynamic and flexible configuration of the filesystem that is seen by Python
programs. Ports that have this functionality provide the :func:`mount` and
:func:`umount` functions, and possibly various filesystem implementations
represented by VFS classes.
.. function:: mount(fsobj, mount_point, *, readonly)
Mount the filesystem object *fsobj* at the location in the VFS given by the
*mount_point* string. *fsobj* can be a a VFS object that has a ``mount()``
method, or a block device. If it's a block device then the filesystem type
is automatically detected (an exception is raised if no filesystem was
recognised). *mount_point* may be ``'/'`` to mount *fsobj* at the root,
or ``'/<name>'`` to mount it at a subdirectory under the root.
If *readonly* is ``True`` then the filesystem is mounted read-only.
During the mount process the method ``mount()`` is called on the filesystem
object.
Will raise ``OSError(EPERM)`` if *mount_point* is already mounted.
.. function:: umount(mount_point)
Unmount a filesystem. *mount_point* can be a string naming the mount location,
or a previously-mounted filesystem object. During the unmount process the
method ``umount()`` is called on the filesystem object.
Will raise ``OSError(EINVAL)`` if *mount_point* is not found.
.. class:: VfsFat(block_dev)
Create a filesystem object that uses the FAT filesystem format. Storage of
the FAT filesystem is provided by *block_dev*.
Objects created by this constructor can be mounted using :func:`mount`.
.. staticmethod:: mkfs(block_dev)
Build a FAT filesystem on *block_dev*.
.. class:: VfsLfs1(block_dev, readsize=32, progsize=32, lookahead=32)
Create a filesystem object that uses the `littlefs v1 filesystem format`_.
Storage of the littlefs filesystem is provided by *block_dev*, which must
support the :ref:`extended interface <block-device-interface>`.
Objects created by this constructor can be mounted using :func:`mount`.
See :ref:`filesystem` for more information.
.. staticmethod:: mkfs(block_dev, readsize=32, progsize=32, lookahead=32)
Build a Lfs1 filesystem on *block_dev*.
.. note:: There are reports of littlefs v1 failing in certain situations,
for details see `littlefs issue 347`_.
.. class:: VfsLfs2(block_dev, readsize=32, progsize=32, lookahead=32, mtime=True)
Create a filesystem object that uses the `littlefs v2 filesystem format`_.
Storage of the littlefs filesystem is provided by *block_dev*, which must
support the :ref:`extended interface <block-device-interface>`.
Objects created by this constructor can be mounted using :func:`mount`.
The *mtime* argument enables modification timestamps for files, stored using
littlefs attributes. This option can be disabled or enabled differently each
mount time and timestamps will only be added or updated if *mtime* is enabled,
otherwise the timestamps will remain untouched. Littlefs v2 filesystems without
timestamps will work without reformatting and timestamps will be added
transparently to existing files once they are opened for writing. When *mtime*
is enabled `os.stat` on files without timestamps will return 0 for the timestamp.
See :ref:`filesystem` for more information.
.. staticmethod:: mkfs(block_dev, readsize=32, progsize=32, lookahead=32)
Build a Lfs2 filesystem on *block_dev*.
.. note:: There are reports of littlefs v2 failing in certain situations,
for details see `littlefs issue 295`_.
.. class:: VfsPosix(root=None)
Create a filesystem object that accesses the host POSIX filesystem.
If *root* is specified then it should be a path in the host filesystem to use
as the root of the ``VfsPosix`` object. Otherwise the current directory of
the host filesystem is used.
.. _littlefs v1 filesystem format: https://github.com/ARMmbed/littlefs/tree/v1
.. _littlefs v2 filesystem format: https://github.com/ARMmbed/littlefs
.. _littlefs issue 295: https://github.com/ARMmbed/littlefs/issues/295
.. _littlefs issue 347: https://github.com/ARMmbed/littlefs/issues/347
Block devices
-------------
A block device is an object which implements the block protocol. This enables a
device to support MicroPython filesystems. The physical hardware is represented
by a user defined class. The :class:`AbstractBlockDev` class is a template for
the design of such a class: MicroPython does not actually provide that class,
but an actual block device class must implement the methods described below.
A concrete implementation of this class will usually allow access to the
memory-like functionality of a piece of hardware (like flash memory). A block
device can be formatted to any supported filesystem and mounted using ``os``
methods.
See :ref:`filesystem` for example implementations of block devices using the
two variants of the block protocol described below.
.. _block-device-interface:
Simple and extended interface
.............................
There are two compatible signatures for the ``readblocks`` and ``writeblocks``
methods (see below), in order to support a variety of use cases. A given block
device may implement one form or the other, or both at the same time. The second
form (with the offset parameter) is referred to as the "extended interface".
Some filesystems (such as littlefs) that require more control over write
operations, for example writing to sub-block regions without erasing, may require
that the block device supports the extended interface.
.. class:: AbstractBlockDev(...)
Construct a block device object. The parameters to the constructor are
dependent on the specific block device.
.. method:: readblocks(block_num, buf)
readblocks(block_num, buf, offset)
The first form reads aligned, multiples of blocks.
Starting at the block given by the index *block_num*, read blocks from
the device into *buf* (an array of bytes).
The number of blocks to read is given by the length of *buf*,
which will be a multiple of the block size.
The second form allows reading at arbitrary locations within a block,
and arbitrary lengths.
Starting at block index *block_num*, and byte offset within that block
of *offset*, read bytes from the device into *buf* (an array of bytes).
The number of bytes to read is given by the length of *buf*.
.. method:: writeblocks(block_num, buf)
writeblocks(block_num, buf, offset)
The first form writes aligned, multiples of blocks, and requires that the
blocks that are written to be first erased (if necessary) by this method.
Starting at the block given by the index *block_num*, write blocks from
*buf* (an array of bytes) to the device.
The number of blocks to write is given by the length of *buf*,
which will be a multiple of the block size.
The second form allows writing at arbitrary locations within a block,
and arbitrary lengths. Only the bytes being written should be changed,
and the caller of this method must ensure that the relevant blocks are
erased via a prior ``ioctl`` call.
Starting at block index *block_num*, and byte offset within that block
of *offset*, write bytes from *buf* (an array of bytes) to the device.
The number of bytes to write is given by the length of *buf*.
Note that implementations must never implicitly erase blocks if the offset
argument is specified, even if it is zero.
.. method:: ioctl(op, arg)
Control the block device and query its parameters. The operation to
perform is given by *op* which is one of the following integers:
- 1 -- initialise the device (*arg* is unused)
- 2 -- shutdown the device (*arg* is unused)
- 3 -- sync the device (*arg* is unused)
- 4 -- get a count of the number of blocks, should return an integer
(*arg* is unused)
- 5 -- get the number of bytes in a block, should return an integer,
or ``None`` in which case the default value of 512 is used
(*arg* is unused)
- 6 -- erase a block, *arg* is the block number to erase
As a minimum ``ioctl(4, ...)`` must be intercepted; for littlefs
``ioctl(6, ...)`` must also be intercepted. The need for others is
hardware dependent.
Prior to any call to ``writeblocks(block, ...)`` littlefs issues
``ioctl(6, block)``. This enables a device driver to erase the block
prior to a write if the hardware requires it. Alternatively a driver
might intercept ``ioctl(6, block)`` and return 0 (success). In this case
the driver assumes responsibility for detecting the need for erasure.
Unless otherwise stated ``ioctl(op, arg)`` can return ``None``.
Consequently an implementation can ignore unused values of ``op``. Where
``op`` is intercepted, the return value for operations 4 and 5 are as
detailed above. Other operations should return 0 on success and non-zero
for failure, with the value returned being an ``OSError`` errno code.

Wyświetl plik

@ -251,7 +251,7 @@ controlling its operation:
.. method:: WM8960.expand_3d(level)
Enable Stereo 3D exansion. *level* is a number between 0 and 15.
Enable Stereo 3D expansion. *level* is a number between 0 and 15.
A value of 0 disables the expansion.
.. method:: WM8960.mono(active)

Wyświetl plik

@ -34,5 +34,5 @@ Methods
These methods implement the simple and extended
:ref:`block protocol <block-device-interface>` defined by
:class:`os.AbstractBlockDev`.
:class:`vfs.AbstractBlockDev`.

Wyświetl plik

@ -37,4 +37,4 @@ Methods
These methods implement the simple and extended
:ref:`block protocol <block-device-interface>` defined by
:class:`os.AbstractBlockDev`.
:class:`vfs.AbstractBlockDev`.

Wyświetl plik

@ -28,7 +28,7 @@ MIMXRT1060-EVK Debug USB D0/D1 D7/D6 D8/D9
MIMXRT1064-EVK Debug USB D0/D1 D7/D6 D8/D9
MIMXRT1170-EVK Debug USB D0/D1 D12/D11 D10/D13
Adafruit Metro M7 - D0/D1 D7/D3 A1/A0
Olimex RT1010Py - RxD/TxD D5/D6 -
Olimex RT1010Py - RxD/TxD D7/D8 D5/D6
Seeed ARCH MIX - J3_19/J3_20 J4_16/J4_17 J4_06/J4_07
================= =========== =========== =========== ===========
@ -319,7 +319,7 @@ MIXMXRT1050-EVKB D10/-/D11/D12/D13 (*) - -
MIXMXRT1060-EVK D10/-/D11/D12/D13 (*) - -
MIXMXRT1064-EVK D10/-/D11/D12/D13 (*) - -
MIXMXRT1170-EVK D10/-/D11/D12/D13 D28/-/D25/D24/D26 -/-/D14/D15/D24
Adafruit Metro M7 -/-/MOSI/MISO/SCK - -
Adafruit Metro M7 -/-/MOSI/MISO/SCK - -
Olimex RT1010Py - CS0/-/SDO/SDI/SCK SDCARD with CS1
Seeed ARCH MIX J4_12/-/J4_14/J4_13/J4_15 J3_09/J3_05/J3_08_J3_11
================= ========================= ======================= ===============
@ -375,7 +375,7 @@ Teensy 4.0 2 33 4 3 2 - - 5
Teensy 4.1 1 23 26 27 7 21 20 8
Teensy 4.1 2 33 4 3 2 - - 5
Seeed Arch MIX 1 J4_09 J4_14 J4_15 J14_13 J4_11 J4_10 J4_10
Adafruit Metro M7 1 D8 D10 D9 D12 D14 D15 D13
Adafruit Metro M7 1 D8 D10 D9 D12 D14 D15 D13
Olimex RT1010Py 1 D8 D6 D7 D4 D1 D2 D3
Olimex RT1010Py 3 - D10 D9 D11 - - -
MIMXRT_DEV 1 "MCK" "SCK_TX" "WS_TX" "SD_TX" "SCK_RX" "WS_RX" "SD_RX"

Wyświetl plik

@ -92,9 +92,7 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
Available Pins follow the ranges and labelling of the respective board, like:
- 0-33 for Teensy 4.0,
- 0-21 for the MIMXRT10xx-EVK board, or 'D0-Dxx', or 'A0-Ann',
- 0-14 for the Olimex RT1010Py board, or 'D0'-'Dxx' and 'A0'-'Ann'
- 'D0-Dxx', or 'A0-Ann' for Teensy 4.0, MIMXRT10xx-EVK ns Olimex board,
- 'J3_xx', 'J4_xx', 'J5_xx' for the Seeed ARCH MIX board,
or the pin names of the Pin.board or Pin.cpu classes.
@ -106,9 +104,9 @@ Notes:
* At the MIMXRT1010_EVK, pins D4, D5 and D9 of the Arduino connector are by
default not connected to the MCU. For details refer to the schematics.
* At the MIMXRT1170_EVK board, the inner rows of the Arduino connectors are assigned as follows:
- D16 - D23: J9, odd pin numbers; D17 is by default not connected.
- D24 - D27: J26, odd pin numbers; J63-J66 have to be closed to enable these pins.
- D29 - D36: J25, odd pin numbers; D29 and D30 are by default not connected.
- 'D16' - 'D23': J9, odd pin numbers; 'D17' is by default not connected.
- 'D24' - 'D27': J26, odd pin numbers; J63-J66 have to be closed to enable these pins.
- 'D29' - 'D36': J25, odd pin numbers; 'D29' and 'D30' are by default not connected.
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
@ -146,22 +144,22 @@ handling signal groups. ::
from machine import Pin, PWM
# create PWM object from a pin and set the frequency and duty cycle
pwm2 = PWM(Pin(2), freq=2000, duty_u16=32768)
pwm2 = PWM(Pin('D2'), freq=2000, duty_u16=32768)
pwm2.freq() # get the current frequency
pwm2.freq(1000) # set/change the frequency
pwm2.duty_u16() # get the current duty cycle, range 0-65535
pwm2.duty_u16(200) # set the duty cycle, range 0-65535
pwm2.deinit() # turn off PWM on the pin
# create a complementary signal pair on Pin 2 and 3
pwm2 = PWM((2, 3), freq=2000, duty_ns=20000)
pwm2 = PWM(('D2', 'D3'), freq=2000, duty_ns=20000)
# Create a group of four synchronized signals.
# Start with Pin(4) at submodule 0, which creates the sync pulse.
pwm4 = PWM(Pin(4), freq=1000, align=PWM.HEAD)
# Pins 5, 6, and 9 are pins at the same module
pwm5 = PWM(Pin(5), freq=1000, duty_u16=10000, align=PWM.HEAD, sync=True)
pwm6 = PWM(Pin(6), freq=1000, duty_u16=20000, align=PWM.HEAD, sync=True)
pwm9 = PWM(Pin(9), freq=1000, duty_u16=30000, align=PWM.HEAD, sync=True)
# Start with Pin('D4') at submodule 0, which creates the sync pulse.
pwm4 = PWM(Pin('D4'), freq=1000, align=PWM.HEAD)
# Pins D5, D6, and D9 are pins at the same module
pwm5 = PWM(Pin('D5'), freq=1000, duty_u16=10000, align=PWM.HEAD, sync=True)
pwm6 = PWM(Pin('D6', freq=1000, duty_u16=20000, align=PWM.HEAD, sync=True)
pwm9 = PWM(Pin('D9'), freq=1000, duty_u16=30000, align=PWM.HEAD, sync=True)
pwm3 # show the PWM objects properties
@ -256,7 +254,7 @@ Use the :ref:`machine.ADC <machine.ADC>` class::
from machine import ADC
adc = ADC(Pin(32)) # create ADC object on ADC pin
adc = ADC(Pin('A2')) # create ADC object on ADC pin
adc.read_u16() # read value, 0-65536 across voltage range 0.0v - 3.3v
The resolution of the ADC is 12 bit with 10 to 11 bit accuracy, irrespective of the
@ -274,7 +272,7 @@ Software SPI (using bit-banging) works on all pins, and is accessed via the
# construct a SoftSPI bus on the given pins
# polarity is the idle state of SCK
# phase=0 means sample on the first edge of SCK, phase=1 means the second
spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin('D0'), mosi=Pin('D2'), miso=Pin('D4'))
spi.init(baudrate=200000) # set the baudrate
@ -303,7 +301,7 @@ rates (up to 30Mhz). Hardware SPI is accessed via the
from machine import SPI, Pin
spi = SPI(0, 10000000)
cs_pin = Pin(6, Pin.OUT, value=1)
cs_pin = Pin('D6', Pin.OUT, value=1)
cs_pin(0)
spi.write('Hello World')
cs_pin(1)
@ -311,7 +309,7 @@ rates (up to 30Mhz). Hardware SPI is accessed via the
For the assignment of Pins to SPI signals, refer to
:ref:`Hardware SPI pinout <mimxrt_spi_pinout>`.
The keyword option cs=n can be used to enable the cs pin 0 or 1 for an automatic cs signal. The
default is cs=-1. Using cs=-1 the automatic cs signal is not created.
default is cs=-1. Using cs=-1 the automatic cs signal is not created.
In that case, cs has to be set by the script. Clearing that assignment requires a power cycle.
Notes:
@ -331,7 +329,7 @@ accessed via the :ref:`machine.SoftI2C <machine.SoftI2C>` class::
from machine import Pin, SoftI2C
i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=100000)
i2c = SoftI2C(scl=Pin('D5'), sda=Pin('D4'), freq=100000)
i2c.scan() # scan for devices
@ -365,7 +363,7 @@ See :ref:`machine.I2S <machine.I2S>`. Example using a Teensy 4.1 board with a si
external Codec like UDA1334.::
from machine import I2S, Pin
i2s = I2S(2, sck=Pin(26), ws=Pin(27), sd=Pin(7),
i2s = I2S(2, sck=Pin('D26'), ws=Pin('D27'), sd=Pin('D7'),
mode=I2S.TX, bts=16,format=I2S.STEREO,
rate=44100,ibuf=40000)
i2s.write(buf) # write buffer of audio samples to I2S device
@ -397,7 +395,7 @@ Example using the Teensy audio shield::
from machine import I2C, I2S, Pin
from sgtl5000 import CODEC
i2s = I2S(1, sck=Pin(21), ws=Pin(20), sd=Pin(7), mck=Pin(23),
i2s = I2S(1, sck=Pin('D21'), ws=Pin('D20'), sd=Pin('D7'), mck=Pin('D23'),
mode=I2S.TX, bits=16,rate=44100,format=I2S.STEREO,
ibuf=40000,
)
@ -445,27 +443,27 @@ SD card
See :ref:`machine.SDCard <machine.SDCard>`::
import machine, os
import machine, os, vfs
sd = machine.SDCard()
fs = os.VfsFat(sd)
os.mount(fs, "/sd") # mount
fs = vfs.VfsFat(sd)
vfs.mount(fs, "/sd") # mount
os.listdir('/sd') # list directory contents
os.umount('/sd') # eject
vfs.umount('/sd') # eject
Note: The i.mx-rt 1011 and 1015 based boards do not support the ``machine.SDCard``
class. For these, the SPI based driver ``sdcard.py`` from the MicroPython drivers
can be used. When using it, you have to overdrive the CS pin of the SPI hardware
module. Example::
import os, sdcard, machine
import vfs, sdcard, machine
cs_pin = "D10"
spi = machine.SPI(0) # SPI0 with cs at Pin "D10" used for SDCARD
cs = machine.Pin(cs_pin, machine.Pin.OUT, value=1)
sd = sdcard.SDCard(spi, cs)
vfs = os.VfsFat(sd)
os.mount(vfs, "/sdcard")
fs = vfs.VfsFat(sd)
vfs.mount(fs, "/sdcard")
OneWire driver
--------------
@ -475,7 +473,7 @@ The OneWire driver is implemented in software and works on all pins::
from machine import Pin
import onewire
ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12
ow = onewire.OneWire(Pin('D12')) # create a OneWire bus on GPIO12
ow.scan() # return a list of devices on the bus
ow.reset() # reset the bus
ow.readbyte() # read a byte
@ -505,12 +503,12 @@ The DHT driver is implemented in software and works on all pins::
import dht
import machine
d = dht.DHT11(machine.Pin(4))
d = dht.DHT11(machine.Pin('D4'))
d.measure()
d.temperature() # eg. 23 (°C)
d.humidity() # eg. 41 (% RH)
d = dht.DHT22(machine.Pin(4))
d = dht.DHT22(machine.Pin('D4'))
d.measure()
d.temperature() # eg. 23.6 (°C)
d.humidity() # eg. 41.3 (% RH)

Wyświetl plik

@ -21,7 +21,7 @@ If needed, you can prevent the use of the SD card by creating an empty file
called ``/flash/SKIPSD``. If this file exists when the pyboard boots
up then the SD card will be skipped and the pyboard will always boot from the
internal filesystem (in this case the SD card won't be mounted but you can still
mount and use it later in your program using ``os.mount``).
mount and use it later in your program using ``vfs.mount``).
(Note that on older versions of the board, ``/flash`` is called ``0:/`` and ``/sd``
is called ``1:/``).

Wyświetl plik

@ -1,9 +1,10 @@
import os
# Directory that the project lives in, aka ../..
SITE_ROOT = '/'.join(os.path.dirname(__file__).split('/')[0:-2])
SITE_ROOT = "/".join(os.path.dirname(__file__).split("/")[0:-2])
TEMPLATE_DIRS = (
"%s/templates/" % SITE_ROOT, # Your custom template directory, before the RTD one to override it.
"%s/readthedocs/templates/" % SITE_ROOT, # Default RTD template dir
"%s/templates/"
% SITE_ROOT, # Your custom template directory, before the RTD one to override it.
"%s/readthedocs/templates/" % SITE_ROOT, # Default RTD template dir
)

Wyświetl plik

@ -211,7 +211,7 @@ two loops:
spi.readinto(buf)
# process data in buf
The first creates a buffer on each pass whereas the second re-uses a pre-allocated
The first creates a buffer on each pass whereas the second reuses a pre-allocated
buffer; this is both faster and more efficient in terms of memory fragmentation.
**Bytes are smaller than ints**

Wyświetl plik

@ -40,7 +40,7 @@ Block devices
-------------
A block device is an instance of a class that implements the
:class:`os.AbstractBlockDev` protocol.
:class:`vfs.AbstractBlockDev` protocol.
Built-in block devices
~~~~~~~~~~~~~~~~~~~~~~
@ -108,16 +108,16 @@ RAM using a ``bytearray``::
It can be used as follows::
import os
import vfs
bdev = RAMBlockDev(512, 50)
os.VfsFat.mkfs(bdev)
os.mount(bdev, '/ramdisk')
vfs.VfsFat.mkfs(bdev)
vfs.mount(bdev, '/ramdisk')
An example of a block device that supports both the simple and extended
interface (i.e. both signatures and behaviours of the
:meth:`os.AbstractBlockDev.readblocks` and
:meth:`os.AbstractBlockDev.writeblocks` methods) is::
:meth:`vfs.AbstractBlockDev.readblocks` and
:meth:`vfs.AbstractBlockDev.writeblocks` methods) is::
class RAMBlockDev:
def __init__(self, block_size, num_blocks):
@ -148,13 +148,13 @@ interface (i.e. both signatures and behaviours of the
return 0
As it supports the extended interface, it can be used with :class:`littlefs
<os.VfsLfs2>`::
<vfs.VfsLfs2>`::
import os
import vfs
bdev = RAMBlockDev(512, 50)
os.VfsLfs2.mkfs(bdev)
os.mount(bdev, '/ramdisk')
vfs.VfsLfs2.mkfs(bdev)
vfs.mount(bdev, '/ramdisk')
Once mounted, the filesystem (regardless of its type) can be used as it
normally would be used from Python code, for example::
@ -166,8 +166,8 @@ normally would be used from Python code, for example::
Filesystems
-----------
MicroPython ports can provide implementations of :class:`FAT <os.VfsFat>`,
:class:`littlefs v1 <os.VfsLfs1>` and :class:`littlefs v2 <os.VfsLfs2>`.
MicroPython ports can provide implementations of :class:`FAT <vfs.VfsFat>`,
:class:`littlefs v1 <vfs.VfsLfs1>` and :class:`littlefs v2 <vfs.VfsLfs2>`.
The following table shows which filesystems are included in the firmware by
default for given port/board combinations, however they can be optionally
@ -197,16 +197,16 @@ recommended to use littlefs instead.
To format the entire flash using FAT::
# ESP8266 and ESP32
import os
os.umount('/')
os.VfsFat.mkfs(bdev)
os.mount(bdev, '/')
import vfs
vfs.umount('/')
vfs.VfsFat.mkfs(bdev)
vfs.mount(bdev, '/')
# STM32
import os, pyb
os.umount('/flash')
os.VfsFat.mkfs(pyb.Flash(start=0))
os.mount(pyb.Flash(start=0), '/flash')
import os, vfs, pyb
vfs.umount('/flash')
vfs.VfsFat.mkfs(pyb.Flash(start=0))
vfs.mount(pyb.Flash(start=0), '/flash')
os.chdir('/flash')
Littlefs
@ -222,16 +222,16 @@ resistant to filesystem corruption.
To format the entire flash using littlefs v2::
# ESP8266 and ESP32
import os
os.umount('/')
os.VfsLfs2.mkfs(bdev)
os.mount(bdev, '/')
import vfs
vfs.umount('/')
vfs.VfsLfs2.mkfs(bdev)
vfs.mount(bdev, '/')
# STM32
import os, pyb
os.umount('/flash')
os.VfsLfs2.mkfs(pyb.Flash(start=0))
os.mount(pyb.Flash(start=0), '/flash')
import os, vfs, pyb
vfs.umount('/flash')
vfs.VfsLfs2.mkfs(pyb.Flash(start=0))
vfs.mount(pyb.Flash(start=0), '/flash')
os.chdir('/flash')
A littlefs filesystem can be still be accessed on a PC over USB MSC using the
@ -264,14 +264,14 @@ block devices spanning a subset of the flash device.
For example, to configure the first 256kiB as FAT (and available over USB MSC),
and the remainder as littlefs::
import os, pyb
os.umount('/flash')
import os, vfs, pyb
vfs.umount('/flash')
p1 = pyb.Flash(start=0, len=256*1024)
p2 = pyb.Flash(start=256*1024)
os.VfsFat.mkfs(p1)
os.VfsLfs2.mkfs(p2)
os.mount(p1, '/flash')
os.mount(p2, '/data')
vfs.VfsFat.mkfs(p1)
vfs.VfsLfs2.mkfs(p2)
vfs.mount(p1, '/flash')
vfs.mount(p2, '/data')
os.chdir('/flash')
This might be useful to make your Python files, configuration and other
@ -282,9 +282,9 @@ failure, etc.
The partition at offset ``0`` will be mounted automatically (and the filesystem
type automatically detected), but you can add::
import os, pyb
import vfs, pyb
p2 = pyb.Flash(start=256*1024)
os.mount(p2, '/data')
vfs.mount(p2, '/data')
to ``boot.py`` to mount the data partition.
@ -297,7 +297,7 @@ define an arbitrary partition layout.
At boot, the partition named "vfs" will be mounted at ``/`` by default, but any
additional partitions can be mounted in your ``boot.py`` using::
import esp32, os
import esp32, vfs
p = esp32.Partition.find(esp32.Partition.TYPE_DATA, label='foo')
os.mount(p, '/foo')
vfs.mount(p, '/foo')

Wyświetl plik

@ -32,7 +32,7 @@ Glossary
callee-owned tuple
This is a MicroPython-specific construct where, for efficiency
reasons, some built-in functions or methods may re-use the same
reasons, some built-in functions or methods may reuse the same
underlying tuple object to return data. This avoids having to allocate
a new tuple for every call, and reduces heap fragmentation. Programs
should not hold references to callee-owned tuples and instead only

Wyświetl plik

@ -31,3 +31,4 @@ implementation and the best practices to use them.
asm_thumb2_index.rst
filesystem.rst
pyboard.py.rst
micropython2_migration.rst

Wyświetl plik

@ -95,6 +95,17 @@ Note: The ``opt`` keyword argument can be set on the various functions, this con
the optimisation level used by the cross-compiler.
See :func:`micropython.opt_level`.
.. function:: add_library(library, library_path, prepend=False)
Register the path to an external named *library*.
The path *library_path* will be automatically searched when using `require`.
By default the added library is added to the end of the list of libraries to
search. Pass ``True`` to *prepend* to add it to the start of the list.
Additionally, the added library can be explicitly requested by using
``require("name", library="library")``.
.. function:: package(package_path, files=None, base_path=".", opt=None)
This is equivalent to copying the "package_path" directory to the device
@ -138,11 +149,13 @@ See :func:`micropython.opt_level`.
You can use the variables above, such as ``$(PORT_DIR)`` in ``base_path``.
.. function:: require(name, unix_ffi=False)
.. function:: require(name, library=None)
Require a package by name (and its dependencies) from :term:`micropython-lib`.
Optionally specify unix_ffi=True to use a module from the unix-ffi directory.
Optionally specify *library* (a string) to reference a package from a
library that has been previously registered with `add_library`. Otherwise
the list of library paths will be used.
.. function:: include(manifest_path)

Wyświetl plik

@ -0,0 +1,81 @@
.. _micropython2_migration:
MicroPython 2.0 Migration Guide
===============================
MicroPython 2.0 is the (currently in development, not yet available) next major
release of MicroPython.
After maintaining API compatibility for almost a decade with the ``1.x`` series, in
order to unblock some project-wide improvements MicroPython 2.0 will introduce a
small number of breaking API changes that will require some programs to be
updated. This guide explains how to update your Python code to accommodate these
changes.
This document is a work-in-progress. As more work is done on MicroPython 2.0,
more items will be added to the lists below.
**Note:** There are currently no MicroPython 2.0 firmware builds available for
download. You can build it yourself by enabling the ``MICROPY_PREVIEW_VERSION_2``
config option. As it gets closer to being ready for release, builds will be
provided for both ``1.x.y`` and ``2.0.0-preview``.
Hardware and peripherals
------------------------
Overview
~~~~~~~~
The goal is to improve consistency in the :mod:`machine` APIs across different
ports, making it easier to write code, documentation, and tutorials that work on
any supported microcontroller.
This means that some ports' APIs need to change to match other ports.
Changes
~~~~~~~
*None yet*
OS & filesystem
---------------
Overview
~~~~~~~~
The primary goal is to support the ability to execute :term:`.mpy files <.mpy
file>` directly from the filesystem without first copying them into RAM. This
improves code deployment time and reduces memory overhead and fragmentation.
Additionally, a further goal is to support a more flexible way of configuring
partitions, filesystem types, and options like USB mass storage.
Changes
~~~~~~~
*None yet*
CPython compatibility
---------------------
Overview
~~~~~~~~
The goal is to improve compatibility with CPython by removing MicroPython
extensions from CPython APIs. In most cases this means moving existing
MicroPython-specific functions or classes to new modules.
This makes it easier to write code that works on both CPython and MicroPython,
which is useful for development and testing.
Changes
~~~~~~~
Introduction of a new module :mod:`vfs`. The following functions and
classes have moved out of :mod:`os` to :mod:`vfs`:
- `os.mount`
- `os.umount`
- `os.VfsFat`
- `os.VfsLfs1`
- `os.VfsLfs2`
- `os.VfsPosix`

Wyświetl plik

@ -100,6 +100,8 @@ The full list of supported commands are:
command output)
- ``port:<path>``: connect to the device with the given path (the first column
from the ``connect list`` command output
- ``rfc2217://<host>:<port>``: connect to the device using serial over TCP
(e.g. a networked serial port based on RFC2217)
- any valid device name/path, to connect to that device
**Note:** Instead of using the ``connect`` command, there are several
@ -109,7 +111,7 @@ The full list of supported commands are:
**Note:** The ``auto`` option will only detect USB serial ports, i.e. a serial
port that has an associated USB VID/PID (i.e. CDC/ACM or FTDI-style
devices). Other types of serial ports
devices). Other types of serial ports will not be auto-detected.
.. _mpremote_command_disconnect:

Wyświetl plik

@ -86,7 +86,8 @@ and .mpy version.
=================== ============
MicroPython release .mpy version
=================== ============
v1.20 and up 6.1
v1.22.0 and up 6.2
v1.20 - v1.21.0 6.1
v1.19.x 6
v1.12 - v1.18 5
v1.11 4
@ -101,6 +102,7 @@ MicroPython repository at which the .mpy version was changed.
=================== ========================================
.mpy version change Git commit
=================== ========================================
6.1 to 6.2 6967ff3c581a66f73e9f3d78975f47528db39980
6 to 6.1 d94141e1473aebae0d3c63aeaa8397651ad6fa01
5 to 6 f2040bfc7ee033e48acef9f289790f3b4e6b74e5
4 to 5 5716c5cf65e9b2cb46c2906f40302401bdd27517

Wyświetl plik

@ -387,15 +387,15 @@ SDCard
The frozen sdcard driver (drivers/sdcard/sdcard.py) is available by connecting microSD card device to hardware SPI0 pins.::
from machine import Pin, SPI
import os, sdcard
import os, vfs, sdcard
spi = SPI(0, baudrate=500000)
cs = Pin.cpu.P103
sd = sdcard.SDCard(spi, cs)
os.mount(sd, '/sd')
vfs.mount(sd, '/sd')
os.listdir('/')
os.chdir('/sd')
os.umount('/sd')
vfs.umount('/sd')
OneWire driver
--------------

Wyświetl plik

@ -0,0 +1,2 @@
sphinx~=7.2.6
sphinxcontrib.jquery==4.1

Wyświetl plik

@ -17,44 +17,53 @@ Adafruit ItsyBitsy M0 Express pin assignment table
=== ==== ============ ==== ==== ====== ====== ====== ======
Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC
=== ==== ============ ==== ==== ====== ====== ====== ======
0 PA11 D0 11 19 0/3 2/3 1/1 0/3
1 PA10 D1 10 18 0/2 2/2 1/0 0/2
2 PA14 D2 14 - 2/2 4/2 3/0 0/4
3 PA09 D3 9 17 0/1 2/1 0/1 1/3
4 PA08 D4 - 16 0/0 2/0 0/0 1/2
5 PA15 D5 15 - 2/3 4/3 3/1 0/5
7 PA21 D7 5 - 5/3 3/3 7/1 0/7
9 PA07 D9 7 7 - 0/3 1/1 -
10 PA18 D10 2 - 1/2 3/2 3/0 0/2
11 PA16 D11 0 - 1/0 3/0 2/0 0/6
12 PA19 D12 3 - 1/3 3/3 3/1 0/3
13 PA17 D13 1 - 1/1 3/1 2/1 0/7
14 PA02 A0 2 0 - - - -
15 PB08 A1 8 2 - 4/0 4/0 -
16 PB09 A2 9 3 - 4/1 4/1 -
17 PA04 A3 4 4 - 0/0 0/0 -
18 PA05 A4 5 5 - 0/1 0/1 -
19 PB02 A5 2 - - 5/0 6/0 -
20 PA22 SDA 6 - 3/0 5/0 4/0 0/4
21 PA23 SCL 7 - 3/1 5/1 4/1 0/5
22 PB10 MOSI 10 - - 4/2 5/0 0/4
23 PA12 MISO 12 - 2/0 4/0 2/0 0/6
24 PB11 SCK 11 - - 4/3 5/1 0/5
25 PA00 DOTSTAR_CLK 0 - - 1/0 2/0 -
26 PA01 DOTSTAR_DATA 1 - - 1/1 2/1 -
27 PB22 FLASH_MOSI 6 - - 5/2 7/0 -
28 PB03 FLASH_MISO 3 - - 5/1 6/1 -
29 PB23 FLASH_SCK 7 - - 5/3 7/1 -
2 PA02 A0 2 0 - - - -
40 PB08 A1 8 2 - 4/0 4/0 -
41 PB09 A2 9 3 - 4/1 4/1 -
4 PA04 A3 4 4 - 0/0 0/0 -
5 PA05 A4 5 5 - 0/1 0/1 -
34 PB02 A5 2 10 - 5/0 6/0 -
11 PA11 D0 11 19 0/3 2/3 1/1 0/3
10 PA10 D1 10 18 0/2 2/2 1/0 0/2
14 PA14 D2 14 - 2/2 4/2 3/0 0/4
9 PA09 D3 9 17 0/1 2/1 0/1 1/3
8 PA08 D4 - 16 0/0 2/0 0/0 1/2
15 PA15 D5 15 - 2/3 4/3 3/1 0/5
21 PA21 D7 5 - 5/3 3/3 7/1 0/7
7 PA07 D9 7 7 - 0/3 1/1 -
18 PA18 D10 2 - 1/2 3/2 3/0 0/2
16 PA16 D11 0 - 1/0 3/0 2/0 0/6
19 PA19 D12 3 - 1/3 3/3 3/1 0/3
17 PA17 D13 1 - 1/1 3/1 2/1 0/7
0 PA00 DOTSTAR_CLK 0 - - 1/0 2/0 -
1 PA01 DOTSTAR_DATA 1 - - 1/1 2/1 -
27 PA27 FLASH_CS 15 - - - - -
35 PB03 FLASH_MISO 3 11 - 5/1 6/1 -
54 PB22 FLASH_MOSI 6 - - 5/2 7/0 -
55 PB23 FLASH_SCK 7 - - 5/3 7/1 -
12 PA12 MISO 12 - 2/0 4/0 2/0 0/6
42 PB10 MOSI 10 - - 4/2 5/0 0/4
43 PB11 SCK 11 - - 4/3 5/1 0/5
23 PA23 SCL 7 - 3/1 5/1 4/1 0/5
22 PA22 SDA 6 - 3/0 5/0 4/0 0/4
30 PA30 SWCLK 10 - - 1/2 1/0 -
31 PA31 SWDIO 11 - - 1/3 1/1 -
24 PA24 USB_DM 12 - 3/2 5/2 5/0 1/2
25 PA25 USB_DP 13 - 3/3 5/3 5/1 1/3
3 PA03 3 1 - - - -
6 PA06 6 6 - 0/2 1/0 -
13 PA13 13 - 2/1 4/1 2/0 0/7
20 PA20 4 - 5/2 3/2 7/0 0/4
28 PA28 8 - - - - -
=== ==== ============ ==== ==== ====== ====== ====== ======
Description of the columns:
- *Pin* - The number that is expected at ``machine.Pin(n)``, if the pin is given
as a number. This is NOT the GPIO number, but the board pin number, as
given in the board specific definition file.
- *GPIO* - The GPIO number.
- *Pin Name* - The name of a Pin which is expected argument to ``machine.Pin("name")``.
as a number.
- *GPIO* - The GPIO name, which can be used as argument to ``machine.Pin("name")``.
- *Pin Name* - The boards name, which can be used as argument to ``machine.Pin("name")``.
- *IRQ* - The IRQ number assigned to that GPIO, used internally by ``Pin.irq()``. When
using ``Pin.irq()``, different pins must use different IRQs
- *ADC* - The ADC channel assigned to the pin. When using ADC, different pins must
@ -183,10 +192,9 @@ Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM
Description of the columns:
- *Pin* - The number that is expected at ``machine.Pin(n)``, if the pin is given
as a number. This is NOT the GPIO number, but the board pin number, as
given in the board specific definition file.
- *GPIO* - The GPIO number.
- *Pin Name* The name of a Pin which is expected argument to ``machine.Pin("name")``.
as a number.
- *GPIO* - The GPIO name, which can be used as argument to ``machine.Pin("name")``.
- *Pin Name* - The boards name, which can be used as argument to ``machine.Pin("name")``.
- *IRQ* - The IRQ number assigned to that GPIO, used internally by ``Pin.irq()``. When
using ``Pin.irq()``, different pins must use different IRQs
- *ADC* - The ADC0/1 channel assigned to the pin. When using ADC, different pins must
@ -340,12 +348,12 @@ Adafruit Metro M4 Airlift pin assignment table
=== ==== ============ ==== ==== ==== ====== ====== ===== ===== =====
Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM
=== ==== ============ ==== ==== ==== ====== ====== ===== ===== =====
2 PA02 A0 2 0 - - - - - -
5 PA05 A1 5 5 - - 0/1 0/1 - -
6 PA06 A2 6 6 - - 0/2 1/0 - -
32 PB00 A3 9 12 - - 5/2 7/0 - -
40 PB08 A4 8 2 0 - 4/0 4/0 - -
41 PB09 A5 9 3 1 - 4/1 4/1 - -
2 PA02 A0 2 0 - - - - - -
5 PA05 A1 5 5 - - 0/1 0/1 - -
6 PA06 A2 6 6 - - 0/2 1/0 - -
32 PB00 A3 9 12 - - 5/2 7/0 - -
40 PB08 A4 8 2 0 - 4/0 4/0 - -
41 PB09 A5 9 3 1 - 4/1 4/1 - -
23 PA23 D0 7 - - 3/1 5/0 4/1 1/7 0/3
22 PA22 D1 6 - - 3/0 5/1 4/0 1/6 0/2
49 PB17 D2 1 - - 5/1 - 6/1 3/1 0/5
@ -356,17 +364,17 @@ Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM
44 PB12 D7 12 - - 4/0 - 4/0 3/0 0/0
21 PA21 D8 5 - - 5/3 3/3 7/1 1/5 0/1
20 PA20 D9 4 - - 5/2 3/2 7/0 1/4 0/0
3 PA03 AREF 3 10 - - - - - -
3 PA03 AREF 3 10 - - - - - -
18 PA18 D10 2 - - 1/2 3/2 3/0 1/2 0/6
19 PA19 D11 3 - - 1/3 3/3 3/1 1/3 0/7
16 PA16 D13 0 - - 1/0 3/1 2/0 1/0 0/4
36 PB04 ESP_BUSY 4 - 6 - - - - -
36 PB04 ESP_BUSY 4 - 6 - - - - -
15 PA15 ESP_CS 15 - - 2/3 4/3 3/1 2/1 1/3
33 PB01 ESP_GPIO0 1 13 - - 5/3 7/1 - -
37 PB05 ESP_RESET 5 - 7 - - - - -
55 PB23 ESP_RTS 7 - - 1/3 5/3 7/1 - -
7 PA07 ESP_RX 7 7 - - 0/3 1/1 - -
4 PA04 ESP_TX 4 4 - - 0/0 0/0 - -
33 PB01 ESP_GPIO0 1 13 - - 5/3 7/1 - -
37 PB05 ESP_RESET 5 - 7 - - - - -
55 PB23 ESP_RTS 7 - - 1/3 5/3 7/1 - -
7 PA07 ESP_RX 7 7 - - 0/3 1/1 - -
4 PA04 ESP_TX 4 4 - - 0/0 0/0 - -
43 PB11 FLASH_CS 12 - - - 4/3 5/1 0/5 1/1
11 PA11 FLASH_HOLD 11 11 - 0/3 2/3 1/1 0/3 1/7
9 PA09 FLASH_MISO 9 9 3 0/1 2/0 0/1 0/1 1/5
@ -375,21 +383,21 @@ Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM
10 PA10 FLASH_WP 10 10 - 0/2 2/2 1/0 0/2 1/6
14 PA14 MISO 14 - - 2/2 4/2 3/0 2/0 1/2
12 PA12 MOSI 12 - - 2/0 4/1 2/0 0/6 1/2
54 PB22 NEOPIXEL 22 - - 1/2 5/2 7/0 - -
38 PB06 RXLED 6 - 8 - - - - -
54 PB22 NEOPIXEL 22 - - 1/2 5/2 7/0 - -
38 PB06 RXLED 6 - 8 - - - - -
13 PA13 SCK 13 - - 2/1 4/0 2/1 0/7 1/3
35 PB03 SCL 9 15 - - 5/1 6/1 - -
34 PB02 SDA 2 14 - - 5/0 6/0 2/2 -
30 PA30 SWCLK 14 - - 7/2 1/2 6/0 2/0 -
31 PA31 SWDIO 15 - - 7/3 1/3 6/1 2/1 -
35 PB03 SCL 9 15 - - 5/1 6/1 - -
34 PB02 SDA 2 14 - - 5/0 6/0 2/2 -
30 PA30 SWCLK 14 - - 7/2 1/2 6/0 2/0 -
31 PA31 SWDIO 15 - - 7/3 1/3 6/1 2/1 -
62 PB30 SWO 14 - - 7/0 5/1 0/0 4/0 0/6
39 PB07 TXLED 7 - 9 - - - - -
24 PA24 USB_DM 8 - - 3/2 5/2 5/0 2/2 -
25 PA25 USB_DP 9 - - 3/3 5/3 5/1 - -
39 PB07 TXLED 7 - 9 - - - - -
24 PA24 USB_DM 8 - - 3/2 5/2 5/0 2/2 -
25 PA25 USB_DP 9 - - 3/3 5/3 5/1 - -
17 PA17 USB_HOSTEN 1 - - 1/1 3/0 2/1 1/1 0/5
0 PA00 - 0 - - - 1/0 2/0 - -
1 PA01 - 1 - - - 1/1 2/1 - -
27 PA27 - 11 - - - - - - -
0 PA00 - 0 - - - 1/0 2/0 - -
1 PA01 - 1 - - - 1/1 2/1 - -
27 PA27 - 11 - - - - - - -
63 PB31 - 15 - - 7/1 5/0 0/1 4/1 0/7
=== ==== ============ ==== ==== ==== ====== ====== ===== ===== =====
@ -862,7 +870,7 @@ Adafruit ItsyBitsy M4 Express :ref:`samd51_pinout_table`.
The default devices at the board are:
- UART 1 at pins PB23/PB22, labelled RXD/TXD
- UART 2 at pins PA13/PA12, labelled RXD/TXD
- I2C 5 at pins PA22/PA23, labelled SDA/SCL
- SPI 4 at pins PB12/PB11/PB13, labelled MOSI, MISO and SCK
- DAC output on pins PA02 and PA05, labelled A0 and A4
@ -876,36 +884,36 @@ The tables shown above were created with small a Python script running on the ta
from machine import Pin
import os
def print_entry(e, txt):
def print_item(e, txt):
print(txt, end=": ")
if e == 255:
print(" - ", end="")
else:
print("%d/%d" % (e >> 4, e & 0x0f), end="")
def print_pininfo(pin, info):
print("%3d" % pin, end=" ")
print("P%c%02d" % ("ABCD"[pin // 32], pin % 32), end="")
print(" %12s" % info[0], end="")
def print_pininfo(pin_id, name, info):
print("%3d" % pin_id, end=" ")
print("%4s %12s" % (info[0], name), end="")
print(" IRQ:%2s" % (info[1] if info[1] != 255 else "-"), end="")
print(" ADC0:%2s" % (info[2] if info[2] != 255 else "-"), end="")
if len(info) == 7:
print_entry(info[3], " Serial1")
print_entry(info[4], " Serial2")
print_entry(info[5], " PWM1" if (info[5] >> 4) < 3 else " TC")
print_entry(info[6], " PWM2")
print_item(info[3], " Serial1")
print_item(info[4], " Serial2")
print_item(info[5], " PWM1" if (info[5] >> 4) < 3 else " TC")
print_item(info[6], " PWM2")
else:
print(" ADC1:%2s" % (info[3] if info[3] != 255 else "-"), end="")
print_entry(info[4], " Serial1")
print_entry(info[5], " Serial2")
print_entry(info[6], " TC")
print_entry(info[7], " PWM1")
print_entry(info[8], " PWM2")
print_item(info[4], " Serial1")
print_item(info[5], " Serial2")
print_item(info[6], " TC")
print_item(info[7], " PWM1")
print_item(info[8], " PWM2")
print()
def tblkey(i):
name = i[1][0]
if name != "-":
name = i[1]
if name != "":
if len(name) < 3:
return " " + name
else:
@ -913,17 +921,25 @@ The tables shown above were created with small a Python script running on the ta
else:
return "zzzzzzz%03d" % i[0]
def table(num = 127):
def table(num=127, sort=True):
pintbl = []
inv_bd = {v: k for k, v in Pin.board.__dict__.items()}
for i in range(num):
try:
pintbl.append((i, pininfo(i)))
p = Pin(i)
pi = pininfo(p)
if p in inv_bd.keys():
name = inv_bd[p]
else:
name = ""
pintbl.append((i, name, pininfo(i)))
except:
pass
# print("not defined")
pintbl.sort(key=tblkey)
if sort:
pintbl.sort(key=tblkey)
for item in pintbl:
print_pininfo(item[0], item[1])
print_pininfo(item[0], item[1], item[2])
table()

Wyświetl plik

@ -9,7 +9,7 @@
{% if is_release %}
<div class="wy-alert wy-alert-danger">
<p>
This is the v{{ release }} version of the MicroPython
This is the {{ release }} version of the MicroPython
documentation. The <a href="/en/latest/{{ pagename }}.html">latest
development version</a> of this page may be more current.
</p>

Wyświetl plik

@ -373,7 +373,7 @@ functions are defined in ``os`` module:
Mounts a block device (like an ``SD`` object) in the specified mount
point. Example::
os.mount(sd, '/sd')
vfs.mount(sd, '/sd')
.. function:: unmount(path)

Wyświetl plik

@ -171,13 +171,13 @@ SD card
See :ref:`machine.SD <machine.SD>`. ::
from machine import SD
import os
import vfs
# clock pin, cmd pin, data0 pin
sd = SD(pins=('GP10', 'GP11', 'GP15'))
# or use default ones for the expansion board
sd = SD()
os.mount(sd, '/sd')
vfs.mount(sd, '/sd')
WLAN (WiFi)
-----------

Wyświetl plik

@ -109,12 +109,12 @@ Disk Access
Use the :ref:`zephyr.DiskAccess <zephyr.DiskAccess>` class to support filesystem::
import os
import vfs
from zephyr import DiskAccess
block_dev = DiskAccess('SDHC') # create a block device object for an SD card
os.VfsFat.mkfs(block_dev) # create FAT filesystem object using the disk storage block
os.mount(block_dev, '/sd') # mount the filesystem at the SD card subdirectory
vfs.VfsFat.mkfs(block_dev) # create FAT filesystem object using the disk storage block
vfs.mount(block_dev, '/sd') # mount the filesystem at the SD card subdirectory
# with the filesystem mounted, files can be manipulated as normal
with open('/sd/hello.txt','w') as f: # open a new file in the directory
@ -126,12 +126,12 @@ Flash Area
Use the :ref:`zephyr.FlashArea <zephyr.FlashArea>` class to support filesystem::
import os
import vfs
from zephyr import FlashArea
block_dev = FlashArea(4, 4096) # creates a block device object in the frdm-k64f flash scratch partition
os.VfsLfs2.mkfs(block_dev) # create filesystem in lfs2 format using the flash block device
os.mount(block_dev, '/flash') # mount the filesystem at the flash subdirectory
vfs.VfsLfs2.mkfs(block_dev) # create filesystem in lfs2 format using the flash block device
vfs.mount(block_dev, '/flash') # mount the filesystem at the flash subdirectory
# with the filesystem mounted, files can be manipulated as normal
with open('/flash/hello.txt','w') as f: # open a new file in the directory

Wyświetl plik

@ -6,14 +6,14 @@ Filesystems and Storage
Storage modules support virtual filesystem with FAT and littlefs formats, backed by either
Zephyr DiskAccess or FlashArea (flash map) APIs depending on which the board supports.
See `os Filesystem Mounting <https://docs.micropython.org/en/latest/library/os.html?highlight=os#filesystem-mounting>`_.
See `vfs Filesystem Mounting <https://docs.micropython.org/en/latest/library/vfs.html?highlight=vfs#filesystem-mounting>`_.
Disk Access
-----------
The :ref:`zephyr.DiskAccess <zephyr.DiskAccess>` class can be used to access storage devices, such as SD cards.
This class uses `Zephyr Disk Access API <https://docs.zephyrproject.org/latest/reference/storage/disk/access.html>`_ and
implements the `os.AbstractBlockDev` protocol.
implements the `vfs.AbstractBlockDev` protocol.
For use with SD card controllers, SD cards must be present at boot & not removed; they will
be auto detected and initialized by filesystem at boot. Use the disk driver interface and a
@ -21,11 +21,11 @@ file system to access SD cards via disk access (see below).
Example usage of FatFS with an SD card on the mimxrt1050_evk board::
import os
import vfs
from zephyr import DiskAccess
bdev = zephyr.DiskAccess('SDHC') # create block device object using DiskAccess
os.VfsFat.mkfs(bdev) # create FAT filesystem object using the disk storage block
os.mount(bdev, '/sd') # mount the filesystem at the SD card subdirectory
vfs.VfsFat.mkfs(bdev) # create FAT filesystem object using the disk storage block
vfs.mount(bdev, '/sd') # mount the filesystem at the SD card subdirectory
with open('/sd/hello.txt','w') as f: # open a new file in the directory
f.write('Hello world') # write to the file
print(open('/sd/hello.txt').read()) # print contents of the file
@ -39,15 +39,15 @@ customize filesystem configurations. To store persistent data on the device, usi
API is recommended (see below).
This class uses `Zephyr Flash map API <https://docs.zephyrproject.org/latest/reference/storage/flash_map/flash_map.html#>`_ and
implements the `os.AbstractBlockDev` protocol.
implements the `vfs.AbstractBlockDev` protocol.
Example usage with the internal flash on the reel_board or the rv32m1_vega_ri5cy board::
import os
import vfs
from zephyr import FlashArea
bdev = FlashArea(FlashArea.STORAGE, 4096) # create block device object using FlashArea
os.VfsLfs2.mkfs(bdev) # create Little filesystem object using the flash area block
os.mount(bdev, '/flash') # mount the filesystem at the flash storage subdirectory
vfs.VfsLfs2.mkfs(bdev) # create Little filesystem object using the flash area block
vfs.mount(bdev, '/flash') # mount the filesystem at the flash storage subdirectory
with open('/flash/hello.txt','w') as f: # open a new file in the directory
f.write('Hello world') # write to the file
print(open('/flash/hello.txt').read()) # print contents of the file

Wyświetl plik

@ -49,14 +49,14 @@
#endif
STATIC void nibble_write(mp_soft_qspi_obj_t *self, uint8_t v) {
static void nibble_write(mp_soft_qspi_obj_t *self, uint8_t v) {
mp_hal_pin_write(self->io0, v & 1);
mp_hal_pin_write(self->io1, (v >> 1) & 1);
mp_hal_pin_write(self->io2, (v >> 2) & 1);
mp_hal_pin_write(self->io3, (v >> 3) & 1);
}
STATIC int mp_soft_qspi_ioctl(void *self_in, uint32_t cmd) {
static int mp_soft_qspi_ioctl(void *self_in, uint32_t cmd) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
switch (cmd) {
@ -80,7 +80,7 @@ STATIC int mp_soft_qspi_ioctl(void *self_in, uint32_t cmd) {
return 0; // success
}
STATIC void mp_soft_qspi_transfer(mp_soft_qspi_obj_t *self, size_t len, const uint8_t *src, uint8_t *dest) {
static void mp_soft_qspi_transfer(mp_soft_qspi_obj_t *self, size_t len, const uint8_t *src, uint8_t *dest) {
// Will run as fast as possible, limited only by CPU speed and GPIO time
mp_hal_pin_input(self->io1);
mp_hal_pin_output(self->io0);
@ -119,7 +119,7 @@ STATIC void mp_soft_qspi_transfer(mp_soft_qspi_obj_t *self, size_t len, const ui
}
}
STATIC void mp_soft_qspi_qread(mp_soft_qspi_obj_t *self, size_t len, uint8_t *buf) {
static void mp_soft_qspi_qread(mp_soft_qspi_obj_t *self, size_t len, uint8_t *buf) {
// Make all IO lines input
mp_hal_pin_input(self->io2);
mp_hal_pin_input(self->io3);
@ -137,7 +137,7 @@ STATIC void mp_soft_qspi_qread(mp_soft_qspi_obj_t *self, size_t len, uint8_t *bu
}
}
STATIC void mp_soft_qspi_qwrite(mp_soft_qspi_obj_t *self, size_t len, const uint8_t *buf) {
static void mp_soft_qspi_qwrite(mp_soft_qspi_obj_t *self, size_t len, const uint8_t *buf) {
// Make all IO lines output
mp_hal_pin_output(self->io2);
mp_hal_pin_output(self->io3);
@ -158,7 +158,7 @@ STATIC void mp_soft_qspi_qwrite(mp_soft_qspi_obj_t *self, size_t len, const uint
//mp_hal_pin_input(self->io1);
}
STATIC int mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) {
static int mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
uint32_t cmd_buf = cmd | data << 8;
CS_LOW(self);
@ -167,7 +167,7 @@ STATIC int mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, u
return 0;
}
STATIC int mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) {
static int mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
uint8_t cmd_buf[5] = {cmd};
uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr);
@ -178,7 +178,7 @@ STATIC int mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t
return 0;
}
STATIC int mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len, uint32_t *dest) {
static int mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len, uint32_t *dest) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
uint32_t cmd_buf = cmd;
CS_LOW(self);
@ -188,7 +188,7 @@ STATIC int mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len, uint32_
return 0;
}
STATIC int mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) {
static int mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
uint8_t cmd_buf[7] = {cmd};
uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr);

Wyświetl plik

@ -49,9 +49,9 @@ extern uint8_t mp_bluetooth_hci_cmd_buf[4 + 256];
#include "uart.h"
// Provided by the port.
extern pyb_uart_obj_t mp_bluetooth_hci_uart_obj;
extern machine_uart_obj_t mp_bluetooth_hci_uart_obj;
STATIC void cywbt_wait_cts_low(void) {
static void cywbt_wait_cts_low(void) {
mp_hal_pin_config(CYW43_PIN_BT_CTS, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0);
for (int i = 0; i < 200; ++i) {
if (mp_hal_pin_read(CYW43_PIN_BT_CTS) == 0) {
@ -64,11 +64,11 @@ STATIC void cywbt_wait_cts_low(void) {
}
#endif
STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
static int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
mp_bluetooth_hci_uart_write((void *)buf, len);
for (int c, i = 0; i < 6; ++i) {
while ((c = mp_bluetooth_hci_uart_readchar()) == -1) {
MICROPY_EVENT_POLL_HOOK
mp_event_wait_indefinite();
}
buf[i] = c;
}
@ -88,7 +88,7 @@ STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
int sz = buf[2] - 3;
for (int c, i = 0; i < sz; ++i) {
while ((c = mp_bluetooth_hci_uart_readchar()) == -1) {
MICROPY_EVENT_POLL_HOOK
mp_event_wait_indefinite();
}
buf[i] = c;
}
@ -96,7 +96,7 @@ STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
return 0;
}
STATIC int cywbt_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *param_buf) {
static int cywbt_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *param_buf) {
uint8_t *buf = mp_bluetooth_hci_cmd_buf;
buf[0] = 0x01;
buf[1] = ocf;
@ -108,19 +108,19 @@ STATIC int cywbt_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *para
return cywbt_hci_cmd_raw(4 + param_len, buf);
}
STATIC void put_le16(uint8_t *buf, uint16_t val) {
static void put_le16(uint8_t *buf, uint16_t val) {
buf[0] = val;
buf[1] = val >> 8;
}
STATIC void put_le32(uint8_t *buf, uint32_t val) {
static void put_le32(uint8_t *buf, uint32_t val) {
buf[0] = val;
buf[1] = val >> 8;
buf[2] = val >> 16;
buf[3] = val >> 24;
}
STATIC int cywbt_set_baudrate(uint32_t baudrate) {
static int cywbt_set_baudrate(uint32_t baudrate) {
uint8_t buf[6];
put_le16(buf, 0);
put_le32(buf + 2, baudrate);
@ -128,7 +128,7 @@ STATIC int cywbt_set_baudrate(uint32_t baudrate) {
}
// download firmware
STATIC int cywbt_download_firmware(const uint8_t *firmware) {
static int cywbt_download_firmware(const uint8_t *firmware) {
cywbt_hci_cmd(0x3f, 0x2e, 0, NULL);
bool last_packet = false;
@ -255,7 +255,7 @@ int mp_bluetooth_hci_controller_deinit(void) {
}
#ifdef CYW43_PIN_BT_DEV_WAKE
STATIC uint32_t bt_sleep_ticks;
static uint32_t bt_sleep_ticks;
#endif
int mp_bluetooth_hci_controller_sleep_maybe(void) {

Wyświetl plik

@ -29,7 +29,10 @@
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "extmod/machine_pulse.h"
#if MICROPY_PY_MACHINE_PULSE
#include "extmod/modmachine.h"
#include "drivers/dht/dht.h"
// Allow the open-drain-high call to be DHT specific for ports that need it
@ -37,7 +40,7 @@
#define mp_hal_pin_od_high_dht mp_hal_pin_od_high
#endif
STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) {
static mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) {
mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in);
mp_hal_pin_open_drain(pin);
@ -92,3 +95,5 @@ timeout:
mp_raise_OSError(MP_ETIMEDOUT);
}
MP_DEFINE_CONST_FUN_OBJ_2(dht_readinto_obj, dht_readinto);
#endif // MICROPY_PY_MACHINE_PULSE

Wyświetl plik

@ -34,23 +34,24 @@
#include <string.h>
#include "py/runtime.h"
#include "modmachine.h"
#include "extmod/machine_spi.h"
#include "mpconfigboard.h"
#include "extmod/modmachine.h"
#ifdef MICROPY_HW_WIFI_LED
#include "led.h"
#endif
#include "esp_hosted_hal.h"
#include "esp_hosted_wifi.h"
#ifndef MICROPY_HW_WIFI_IRQ
#define MICROPY_HW_WIFI_IRQ MICROPY_HW_WIFI_HANDSHAKE
#endif
extern void mod_network_poll_events(void);
STATIC mp_obj_t esp_hosted_pin_irq_callback(mp_obj_t self_in) {
extern void mod_network_poll_events(void);
static mp_obj_t esp_hosted_pin_irq_callback(mp_obj_t self_in) {
#ifdef MICROPY_HW_WIFI_LED
led_toggle(MICROPY_HW_WIFI_LED);
#endif
mod_network_poll_events();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_hosted_pin_irq_callback_obj, esp_hosted_pin_irq_callback);
static MP_DEFINE_CONST_FUN_OBJ_1(esp_hosted_pin_irq_callback_obj, esp_hosted_pin_irq_callback);
MP_WEAK int esp_hosted_hal_init(uint32_t mode) {
// Perform a hard reset and set pins to their defaults.
@ -64,34 +65,16 @@ MP_WEAK int esp_hosted_hal_init(uint32_t mode) {
mp_hal_pin_input(MICROPY_HW_WIFI_HANDSHAKE);
mp_hal_pin_input(MICROPY_HW_WIFI_DATAREADY);
// Enable Pin-IRQ for the handshake PIN to call esp_hosted_wifi_poll()
mp_obj_t irq_rising_attr[2];
mp_load_method_maybe((mp_obj_t)MICROPY_HW_WIFI_IRQ, MP_QSTR_IRQ_RISING, irq_rising_attr);
if (irq_rising_attr[0] != MP_OBJ_NULL && irq_rising_attr[1] == MP_OBJ_NULL) { // value for IRQ rising found
mp_obj_t pin_args[] = {
NULL, // Method pointer
(mp_obj_t)MICROPY_HW_WIFI_IRQ, // Pin object
(mp_obj_t)&esp_hosted_pin_irq_callback_obj, // Callback function object
NULL, // The Rising edge value is set below.
mp_const_true, // Hard IRQ, since the actual polling is scheduled.
};
pin_args[3] = irq_rising_attr[0];
mp_load_method_maybe((mp_obj_t)MICROPY_HW_WIFI_IRQ, MP_QSTR_irq, pin_args);
if (pin_args[0] != MP_OBJ_NULL && pin_args[1] != MP_OBJ_NULL) {
mp_call_method_n_kw(3, 0, pin_args);
}
}
// Initialize SPI.
mp_obj_t args[] = {
MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_ID),
MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_BAUDRATE),
MP_OBJ_NEW_QSTR(MP_QSTR_phase), MP_OBJ_NEW_SMALL_INT(0),
MP_OBJ_NEW_QSTR(MP_QSTR_polarity), MP_OBJ_NEW_SMALL_INT(1),
};
MP_STATE_PORT(mp_wifi_spi) =
MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, make_new)((mp_obj_t)&machine_spi_type, 2, 1, args);
MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, make_new)((mp_obj_t)&machine_spi_type, 2, 2, args);
// SPI might change the direction/mode of CS pin,
// set it to GPIO again just in case.
@ -101,16 +84,8 @@ MP_WEAK int esp_hosted_hal_init(uint32_t mode) {
}
MP_WEAK int esp_hosted_hal_deinit(void) {
// Disable Pin-IRQ for the handshake PIN
mp_obj_t pin_args[] = {
NULL, // Method pointer
(mp_obj_t)MICROPY_HW_WIFI_IRQ, // Pin object
mp_const_none // Set to None
};
mp_load_method_maybe((mp_obj_t)MICROPY_HW_WIFI_IRQ, MP_QSTR_irq, pin_args);
if (pin_args[0] && pin_args[1]) {
mp_call_method_n_kw(1, 0, pin_args);
}
// Disable pin IRQ.
esp_hosted_hal_irq_enable(false);
// Remove all network interfaces and reset wifi state.
esp_hosted_wifi_deinit();
@ -134,6 +109,43 @@ MP_WEAK int esp_hosted_hal_deinit(void) {
return 0;
}
MP_WEAK void esp_hosted_hal_irq_enable(bool enable) {
#ifdef MICROPY_HW_WIFI_IRQ_PIN
// Disable Pin-IRQ for the handshake PIN
mp_obj_t pin_args[] = {
NULL, // Method pointer
(mp_obj_t)MICROPY_HW_WIFI_IRQ_PIN, // Pin object
mp_const_none // Set to None
};
mp_load_method_maybe((mp_obj_t)MICROPY_HW_WIFI_IRQ_PIN, MP_QSTR_irq, pin_args);
if (pin_args[0] && pin_args[1]) {
mp_call_method_n_kw(1, 0, pin_args);
}
if (enable) {
// Enable Pin-IRQ for the handshake PIN to call esp_hosted_wifi_poll()
mp_obj_t irq_rising_attr[2];
mp_load_method_maybe((mp_obj_t)MICROPY_HW_WIFI_IRQ_PIN, MP_QSTR_IRQ_RISING, irq_rising_attr);
if (irq_rising_attr[0] != MP_OBJ_NULL && irq_rising_attr[1] == MP_OBJ_NULL) {
// value for IRQ rising found
mp_obj_t pin_args[] = {
NULL, // Method pointer
(mp_obj_t)MICROPY_HW_WIFI_IRQ_PIN, // Pin object
(mp_obj_t)&esp_hosted_pin_irq_callback_obj, // Callback function object
NULL, // The Rising edge value is set below.
mp_const_true, // Hard IRQ, since the actual polling is scheduled.
};
pin_args[3] = irq_rising_attr[0];
mp_load_method_maybe((mp_obj_t)MICROPY_HW_WIFI_IRQ_PIN, MP_QSTR_irq, pin_args);
if (pin_args[0] != MP_OBJ_NULL && pin_args[1] != MP_OBJ_NULL) {
mp_call_method_n_kw(3, 0, pin_args);
}
}
}
#endif
}
MP_WEAK int esp_hosted_hal_atomic_enter(void) {
#if MICROPY_ENABLE_SCHEDULER
mp_sched_lock();
@ -149,7 +161,7 @@ MP_WEAK int esp_hosted_hal_atomic_exit(void) {
}
MP_WEAK bool esp_hosted_hal_data_ready(void) {
return mp_hal_pin_read(MICROPY_HW_WIFI_DATAREADY) && mp_hal_pin_read(MICROPY_HW_WIFI_HANDSHAKE);
return mp_hal_pin_read(MICROPY_HW_WIFI_DATAREADY);
}
MP_WEAK int esp_hosted_hal_spi_transfer(const uint8_t *tx_buf, uint8_t *rx_buf, uint32_t size) {
@ -158,7 +170,8 @@ MP_WEAK int esp_hosted_hal_spi_transfer(const uint8_t *tx_buf, uint8_t *rx_buf,
// Wait for handshake pin to go high.
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(1)) {
if (mp_hal_pin_read(MICROPY_HW_WIFI_HANDSHAKE)) {
if (mp_hal_pin_read(MICROPY_HW_WIFI_HANDSHAKE) &&
(rx_buf == NULL || mp_hal_pin_read(MICROPY_HW_WIFI_DATAREADY))) {
break;
}
if ((mp_hal_ticks_ms() - start) >= 1000) {
@ -171,6 +184,11 @@ MP_WEAK int esp_hosted_hal_spi_transfer(const uint8_t *tx_buf, uint8_t *rx_buf,
mp_hal_delay_us(10);
spi_proto->transfer(mp_wifi_spi, size, tx_buf, rx_buf);
mp_hal_pin_write(MICROPY_HW_WIFI_SPI_CS, 1);
mp_hal_delay_us(100);
if (esp_hosted_hal_data_ready()) {
mod_network_poll_events();
}
return 0;
}

Wyświetl plik

@ -68,6 +68,7 @@ typedef enum {
// Note A default machine-based implementation is provided in esp_hosted_hal.c.
int esp_hosted_hal_init(uint32_t mode);
int esp_hosted_hal_deinit(void);
void esp_hosted_hal_irq_enable(bool enable);
bool esp_hosted_hal_data_ready(void);
int esp_hosted_hal_atomic_enter(void);
int esp_hosted_hal_atomic_exit(void);

Wyświetl plik

@ -29,8 +29,6 @@
#ifndef MICROPY_INCLUDED_DRIVERS_ESP_HOSTED_INTERNAL_H
#define MICROPY_INCLUDED_DRIVERS_ESP_HOSTED_INTERNAL_H
#define ESP_HOSTED_DEBUG (0)
#define ESP_FRAME_MAX_SIZE (1600)
#define ESP_FRAME_MAX_PAYLOAD (ESP_FRAME_MAX_SIZE - sizeof(esp_header_t))
#define ESP_FRAME_FLAGS_FRAGMENT (1 << 0)

Wyświetl plik

@ -51,7 +51,7 @@
static err_t netif_struct_init(struct netif *netif) {
netif->linkoutput = esp_hosted_netif_output;
netif->output = etharp_output;
netif->mtu = 1500;
netif->mtu = ESP_FRAME_MAX_PAYLOAD;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP;
esp_hosted_wifi_get_mac(netif->name[1] - '0', netif->hwaddr);
netif->hwaddr_len = sizeof(netif->hwaddr);

Wyświetl plik

@ -476,6 +476,10 @@ int esp_hosted_wifi_init(uint32_t itf) {
esp_hosted_netif_init(&esp_state, itf);
info_printf("esp_hosted_init() initialized itf %lu\n", itf);
}
// Re/enable IRQ pin.
esp_hosted_hal_irq_enable(true);
return 0;
}

Wyświetl plik

@ -56,21 +56,21 @@
#define PAGE_SIZE (256) // maximum bytes we can write in one SPI transfer
#define SECTOR_SIZE MP_SPIFLASH_ERASE_BLOCK_SIZE
STATIC void mp_spiflash_acquire_bus(mp_spiflash_t *self) {
static void mp_spiflash_acquire_bus(mp_spiflash_t *self) {
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_QSPI) {
c->bus.u_qspi.proto->ioctl(c->bus.u_qspi.data, MP_QSPI_IOCTL_BUS_ACQUIRE);
}
}
STATIC void mp_spiflash_release_bus(mp_spiflash_t *self) {
static void mp_spiflash_release_bus(mp_spiflash_t *self) {
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_QSPI) {
c->bus.u_qspi.proto->ioctl(c->bus.u_qspi.data, MP_QSPI_IOCTL_BUS_RELEASE);
}
}
STATIC int mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t len, uint32_t data) {
static int mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t len, uint32_t data) {
int ret = 0;
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
@ -84,7 +84,7 @@ STATIC int mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t l
return ret;
}
STATIC int mp_spiflash_transfer_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src, uint8_t *dest) {
static int mp_spiflash_transfer_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src, uint8_t *dest) {
int ret = 0;
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
@ -109,7 +109,7 @@ STATIC int mp_spiflash_transfer_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd,
return ret;
}
STATIC int mp_spiflash_read_cmd(mp_spiflash_t *self, uint8_t cmd, size_t len, uint32_t *dest) {
static int mp_spiflash_read_cmd(mp_spiflash_t *self, uint8_t cmd, size_t len, uint32_t *dest) {
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
mp_hal_pin_write(c->bus.u_spi.cs, 0);
@ -122,7 +122,7 @@ STATIC int mp_spiflash_read_cmd(mp_spiflash_t *self, uint8_t cmd, size_t len, ui
}
}
STATIC int mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
static int mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
const mp_spiflash_config_t *c = self->config;
uint8_t cmd;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
@ -133,11 +133,11 @@ STATIC int mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len,
return mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, NULL, dest);
}
STATIC int mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) {
static int mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) {
return mp_spiflash_write_cmd_data(self, cmd, 0, 0);
}
STATIC int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, uint32_t timeout) {
static int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, uint32_t timeout) {
do {
uint32_t sr;
int ret = mp_spiflash_read_cmd(self, CMD_RDSR, 1, &sr);
@ -152,11 +152,11 @@ STATIC int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, u
return -MP_ETIMEDOUT;
}
STATIC int mp_spiflash_wait_wel1(mp_spiflash_t *self) {
static int mp_spiflash_wait_wel1(mp_spiflash_t *self) {
return mp_spiflash_wait_sr(self, 2, 2, WAIT_SR_TIMEOUT);
}
STATIC int mp_spiflash_wait_wip0(mp_spiflash_t *self) {
static int mp_spiflash_wait_wip0(mp_spiflash_t *self) {
return mp_spiflash_wait_sr(self, 1, 0, WAIT_SR_TIMEOUT);
}
@ -219,7 +219,7 @@ void mp_spiflash_deepsleep(mp_spiflash_t *self, int value) {
}
}
STATIC int mp_spiflash_erase_block_internal(mp_spiflash_t *self, uint32_t addr) {
static int mp_spiflash_erase_block_internal(mp_spiflash_t *self, uint32_t addr) {
int ret = 0;
// enable writes
ret = mp_spiflash_write_cmd(self, CMD_WREN);
@ -244,7 +244,7 @@ STATIC int mp_spiflash_erase_block_internal(mp_spiflash_t *self, uint32_t addr)
return mp_spiflash_wait_wip0(self);
}
STATIC int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
static int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
int ret = 0;
// enable writes
ret = mp_spiflash_write_cmd(self, CMD_WREN);
@ -361,7 +361,7 @@ int mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint
return ret;
}
STATIC int mp_spiflash_cache_flush_internal(mp_spiflash_t *self) {
static int mp_spiflash_cache_flush_internal(mp_spiflash_t *self) {
#if USE_WR_DELAY
if (!(self->flags & 1)) {
return 0;
@ -396,7 +396,7 @@ int mp_spiflash_cache_flush(mp_spiflash_t *self) {
return ret;
}
STATIC int mp_spiflash_cached_write_part(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
static int mp_spiflash_cached_write_part(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
// Align to 4096 sector
uint32_t offset = addr & 0xfff;
uint32_t sec = addr >> 12;

Wyświetl plik

@ -42,9 +42,13 @@
#define NINA_GPIO_MODE (0x50)
#define NINA_GPIO_READ (0x53)
#define NINA_GPIO_READ_ANALOG (0x54)
#define NINA_GPIO_WRITE (0x51)
#define NINA_GPIO_IS_INPUT_ONLY(p) ((p >= 34 && p <= 36) || (p == 39))
#define NINA_GPIO_IS_INPUT_ONLY(p) ((p >= 3 && p <= 6))
#define NINA_GPIO_IS_ADC_CHANNEL(p) ((p >= 3 && p <= 6))
// This maps logical pin ID (0..MICROPY_HW_PIN_EXT_COUNT) to
// physical pins on the Nina module.
static uint8_t pin_map[MICROPY_HW_PIN_EXT_COUNT] = {
27, // LEDR
25, // LEDG
@ -55,10 +59,30 @@ static uint8_t pin_map[MICROPY_HW_PIN_EXT_COUNT] = {
35, // A7
};
// This maps logical pin ID (0..MICROPY_HW_PIN_EXT_COUNT) to
// ADC channel numbers on the Nina module.
static uint8_t adc_map[MICROPY_HW_PIN_EXT_COUNT] = {
-1, // LEDR
-1, // LEDG
-1, // LEDB
6, // A4
3, // A5
0, // A6
7, // A7
};
void machine_pin_ext_init(void) {
nina_init();
}
bool machine_pin_ext_is_adc_channel(const machine_pin_obj_t *self) {
return NINA_GPIO_IS_ADC_CHANNEL(self->id);
}
uint32_t machine_pin_ext_to_adc_channel(const machine_pin_obj_t *self) {
return adc_map[self->id];
}
void machine_pin_ext_set(machine_pin_obj_t *self, bool value) {
if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) {
uint8_t buf[] = {pin_map[self->id], value};
@ -76,8 +100,14 @@ bool machine_pin_ext_get(machine_pin_obj_t *self) {
return value;
}
uint16_t machine_pin_ext_read_u16(uint32_t channel) {
uint16_t buf = channel;
nina_ioctl(NINA_GPIO_READ_ANALOG, sizeof(buf), (uint8_t *)&buf, 0);
return buf;
}
void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value) {
if (mode == MACHINE_PIN_MODE_IN) {
if (mode == MACHINE_PIN_MODE_IN || mode == MACHINE_PIN_MODE_ANALOG) {
mode = NINA_GPIO_INPUT;
self->is_output = false;
} else if (mode == MACHINE_PIN_MODE_OUT) {
@ -89,7 +119,7 @@ void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value) {
if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) {
uint8_t buf[] = {pin_map[self->id], mode};
if (mode == NINA_GPIO_OUTPUT) {
if (NINA_GPIO_IS_INPUT_ONLY(buf[0])) {
if (NINA_GPIO_IS_INPUT_ONLY(self->id)) {
mp_raise_ValueError("only Pin.IN is supported for this pin");
}
machine_pin_ext_set(self, value);

Some files were not shown because too many files have changed in this diff Show More