19 Commits

Author SHA1 Message Date
Damien George
8cd15829e2 all: Bump version to 1.22.2.
Signed-off-by: Damien George <damien@micropython.org>
2024-02-20 22:59:55 +11:00
Damien George
ee3c9ccb54 esp32: Increase NimBLE task stack size and overflow detection headroom.
The Python BLE IRQ handler will most likely run on the NimBLE task, so its
C stack must be large enough to accommodate reasonably complicated Python
code (eg a few call depths).  So increase this stack size.

Also increase the headroom from 1024 to 2048 bytes.  This is needed because
(1) the esp32 architecture uses a fair amount of stack in general; and (2)
by the time execution gets to setting the Python stack top via
`mp_stack_set_top()` in this interlock code, about 600 bytes of stack are
already used, which reduces the amount available for Python.

Fixes issue #12349.

Signed-off-by: Damien George <damien@micropython.org>
2024-02-16 10:51:11 +11:00
Damien George
e72d03855e esp32/mpnimbleport: Release the GIL while doing NimBLE port deinit.
In case callbacks must run (eg a disconnect event happens during the
deinit) and the GIL must be obtained to run the callback.

Fixes part of issue #12349.

Signed-off-by: Damien George <damien@micropython.org>
2024-02-16 10:51:00 +11:00
Damien George
02df2b09d4 extmod/btstack: Reset pending_value_handle before calling read-done cb.
Similar to the previous commit but for MP_BLUETOOTH_IRQ_GATTC_READ_DONE:
the pending_value_handle needs to be reset before calling
mp_bluetooth_gattc_on_read_write_status(), which will call the Python IRQ
handler, which may in turn call back into BTstack to perform an action like
a write.  In that case the pending_value_handle will need to be available
for the write/read/etc to proceed.

Fixes issue #13634.

Signed-off-by: Damien George <damien@micropython.org>
2024-02-16 10:50:43 +11:00
Damien George
e7ff724a87 extmod/btstack: Reset pending_value_handle before calling write-done cb.
The pending_value_handle needs to be freed and reset before calling
mp_bluetooth_gattc_on_read_write_status(), which will call the Python IRQ
handler, which may in turn call back into BTstack to perform an action like
a write.  In that case the pending_value_handle will need to be available
for the write/read/etc to proceed.

Fixes issue #13611.

Signed-off-by: Damien George <damien@micropython.org>
2024-02-16 10:50:35 +11:00
Takeo Takahashi
cc7cfc7e8d renesas-ra/ra/ra_i2c: Fix 1 byte and 2 bytes read issue.
Tested on Portenta C33 with AT24256B (addrsize=16) and SSD1306.

Fixes issue #13280.

Signed-off-by: Takeo Takahashi <takeo.takahashi.xv@renesas.com>
2024-02-16 10:49:24 +11:00
Damien George
b979c5a92a py/compile: Fix potential Py-stack overflow in try-finally with return.
If a return is executed within the try block of a try-finally then the
return value is stored on the top of the Python stack during the execution
of the finally block.  In this case the Python stack is one larger than it
normally would be in the finally block.

Prior to this commit, the compiler was not taking this case into account
and could have a Python stack overflow if the Python stack used by the
finally block was more than that used elsewhere in the function.  In such
a scenario the last argument of the function would be clobbered by the
top-most temporary value used in the deepest Python expression/statement.

This commit fixes that case by making sure enough Python stack is allocated
to the function.

Fixes issue #13562.

Signed-off-by: Damien George <damien@micropython.org>
2024-02-16 10:49:14 +11:00
Damien George
f53ee9f12b rp2: Change machine.I2S and rp2.DMA to use shared DMA IRQ handlers.
These separate drivers must share the DMA resource with each other.

Fixes issue #13380.

Signed-off-by: Damien George <damien@micropython.org>
2024-02-16 10:48:51 +11:00
Damien George
2531a15200 extmod/modssl_mbedtls: Fix cipher iteration in SSLContext.get_ciphers.
Prior to this commit it would skip every second cipher returned from
mbedtls.

The corresponding test is also updated and now passes on esp32, rp2, stm32
and unix.

Signed-off-by: Damien George <damien@micropython.org>
2024-02-16 10:48:30 +11:00
Kwabena W. Agyeman
8b6e89a8ca mimxrt/modmachine: Fix deepsleep wakeup pin ifdef.
Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
2024-02-16 10:47:40 +11:00
Damien George
a2e9ab362b extmod/asyncio: Support gather of tasks that finish early.
Adds support to asyncio.gather() for the case that one or more (or all)
sub-tasks finish and/or raise an exception before the gather starts.

Signed-off-by: Damien George <damien@micropython.org>
2024-02-16 10:47:00 +11:00
iabdalkader
1e8cc6c503 renesas-ra/boards/ARDUINO_PORTENTA_C33: Fix the RTC clock source.
Switch the RTC clock source to Sub-clock (XCIN). This board has an
accurate LSE crystal, and it should be used for the RTC clock
source.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-02-16 10:45:34 +11:00
iabdalkader
4c7d955a62 renesas-ra/ra: Fix SysTick clock source.
The SysTick_Config function must use the system/CPU clock to configure the
ticks.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-02-16 10:45:11 +11:00
robert-hh
068aa28fc5 rp2/machine_uart: Fix event wait in uart.flush() and uart.read().
Do not wait in the worst case up to the timeout.

Fixes issue #13377.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-02-16 10:44:40 +11:00
Nicko van Someren
d5f3fcd935 rp2/rp2_dma: Fix fetching 'write' buffers for writing not reading.
Signed-off-by: Nicko van Someren <nicko@nicko.org>
2024-02-16 10:44:10 +11:00
Damien George
9b8c64c9ce all: Bump version to 1.22.1.
Signed-off-by: Damien George <damien@micropython.org>
2024-01-05 12:33:34 +11:00
Damien George
ac5e0b9f62 rp2/mpthreadport: Fix race with IRQ when entering atomic section.
Prior to this commit there is a potential deadlock in
mp_thread_begin_atomic_section(), when obtaining the atomic_mutex, in the
following situation:
- main thread calls mp_thread_begin_atomic_section() (for whatever reason,
  doesn't matter)
- the second core is running so the main thread grabs the mutex via the
  call mp_thread_mutex_lock(&atomic_mutex, 1), and this succeeds
- before the main thread has a chance to run save_and_disable_interrupts()
  a USB IRQ comes in and the main thread jumps off to process this IRQ
- that USB processing triggers a call to the dcd_event_handler() wrapper
  from commit bcbdee2357
- that then calls mp_sched_schedule_node()
- that then attempts to obtain the atomic section, calling
  mp_thread_begin_atomic_section()
- that call then blocks trying to obtain atomic_mutex
- core0 is now deadlocked on itself, because the main thread has the mutex
  but the IRQ handler (which preempted the main thread) is blocked waiting
  for the mutex, which will never be free

The solution in this commit is to use mutex enter/exit functions that also
atomically disable/restore interrupts.

Fixes issues #12980 and #13288.

Signed-off-by: Damien George <damien@micropython.org>
2024-01-05 12:33:10 +11:00
Damien George
61b8361f5f rp2/mutex_extra: Implement additional mutex functions.
These allow entering/exiting a mutex and also disabling/restoring
interrupts, in an atomic way.

Signed-off-by: Damien George <damien@micropython.org>
2024-01-05 12:33:10 +11:00
Damien George
4b4f6011e8 rp2/rp2_flash: Lockout second core only when doing flash erase/write.
Using the multicore lockout feature in the general atomic section makes it
much more difficult to get correct.

Signed-off-by: Damien George <damien@micropython.org>
2024-01-05 12:33:10 +11:00
1320 changed files with 14547 additions and 43701 deletions

View File

@@ -1,12 +1,3 @@
# all: Prune trailing whitespace.
dda9b9c6da5d3c31fa8769e581a753e95a270803
# all: Remove the "STATIC" macro and just use "static" instead.
decf8e6a8bb940d5829ca3296790631fcece7b21
# renesas-ra: Fix spelling mistakes found by codespell.
b3f2f18f927fa2fad10daf63d8c391331f5edf58
# all: Update Python formatting to ruff-format.
bbd8760bd9a2302e5abee29db279102bb11d7732

25
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

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

View File

@@ -1,107 +0,0 @@
name: Bug report
description: Report a bug or unexpected behaviour
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Please provide as much detail as you can, it really helps us find and fix bugs faster.
#### Not a bug report?
* If you have a question \"How Do I ...?\", please post it on [GitHub Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead of here.
* For missing or incorrect documentation, or feature requests, then please [choose a different issue type](https://github.com/micropython/micropython/issues/new/choose).
- 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.

16
.github/ISSUE_TEMPLATE/documentation.md vendored Normal file
View File

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

View File

@@ -1,44 +0,0 @@
name: Documentation issue
description: Report areas of the documentation or examples that need improvement
title: "docs: "
labels: ["documentation"]
body:
- type: markdown
attributes:
value: |
This form is for reporting issues with the documentation or examples provided with MicroPython.
If you have a general question \"How Do I ...?\", please post it on [GitHub Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead of here.
- 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.

View File

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

View File

@@ -1,65 +0,0 @@
name: Feature request
description: Request a feature or improvement
labels: ['enhancement']
body:
- type: markdown
attributes:
value: |
This form is for requesting features or improvements in MicroPython.
#### Get feedback first
Before submitting a new feature idea here, suggest starting a discussion on [Discord](https://discord.gg/RB8HZSAExQ) or [GitHub Discussions](https://github.com/orgs/micropython/discussions/) to get early feedback from the community and maintainers.
#### Not a MicroPython core feature?
* If you have a question \"How Do I ...?\", please post it on GitHub Discussions or Discord instead of here.
* Could this feature be implemented as a pure Python library? If so, please open the request on the [micropython-lib repository](https://github.com/micropython/micropython-lib/issues) instead.
- 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.

16
.github/ISSUE_TEMPLATE/security.md vendored Normal file
View File

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

View File

@@ -1,59 +0,0 @@
name: Security report
description: Report a security issue or vulnerability in MicroPython
labels: ["security"]
body:
- type: markdown
attributes:
value: |
This form is for reporting security issues in MicroPython that are not readily exploitable.
1. For issues that are readily exploitable or have high impact, please email contact@micropython.org instead.
1. If this is a question about security, please ask it in [Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead.
- 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

View File

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

View File

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

View File

@@ -8,15 +8,9 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'ports/bare-arm/**'
- 'ports/mimxrt/**'
- 'ports/minimal/**'
- 'ports/rp2/**'
- 'ports/samd/**'
- 'ports/stm32/**'
- 'ports/unix/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}

View File

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

View File

@@ -35,7 +35,7 @@ jobs:
- name: Cached ESP-IDF install
id: cache_esp_idf
uses: actions/cache@v4
uses: actions/cache@v3
with:
path: |
./esp-idf/

View File

@@ -20,13 +20,8 @@ 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

View File

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

View File

@@ -25,7 +25,6 @@ jobs:
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

View File

@@ -88,11 +88,10 @@ jobs:
(cd ports/unix && gcov -o build-coverage/py ../../py/*.c || true)
(cd ports/unix && gcov -o build-coverage/extmod ../../extmod/*.c || true)
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v3
with:
fail_ci_if_error: true
verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures

View File

@@ -18,134 +18,7 @@ concurrency:
cancel-in-progress: true
jobs:
build-vs:
strategy:
fail-fast: false
matrix:
platform: [x86, x64]
configuration: [Debug, Release]
variant: [dev, standard]
visualstudio: ['2017', '2019', '2022']
include:
- visualstudio: '2017'
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:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

View File

@@ -1,13 +1,11 @@
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Python code lint and formatting with ruff
on: [push, pull_request]
jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# ruff version should be kept in sync with .pre-commit-config.yaml
- run: pip install --user ruff==0.1.3
- run: ruff check --output-format=github .
- run: ruff format --diff .

11
.gitmodules vendored
View File

@@ -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/micropython/berkeley-db-1.xx
url = https://github.com/pfalcon/berkeley-db-1.xx
[submodule "lib/stm32lib"]
path = lib/stm32lib
url = https://github.com/micropython/stm32lib
@@ -59,12 +59,3 @@
[submodule "lib/protobuf-c"]
path = lib/protobuf-c
url = https://github.com/protobuf-c/protobuf-c.git
[submodule "lib/open-amp"]
path = lib/open-amp
url = https://github.com/OpenAMP/open-amp.git
[submodule "lib/libmetal"]
path = lib/libmetal
url = https://github.com/OpenAMP/libmetal.git
[submodule "lib/arduino-lib"]
path = lib/arduino-lib
url = https://github.com/arduino/arduino-lib-mpy.git

View File

@@ -12,16 +12,7 @@ repos:
verbose: true
stages: [commit-msg]
- repo: https://github.com/charliermarsh/ruff-pre-commit
# Version should be kept in sync with .github/workflows/ruff.yml
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

View File

@@ -104,22 +104,6 @@ This command may work, please raise a new Issue if it doesn't:
curl -L https://github.com/Homebrew/homebrew-core/raw/2b07d8192623365078a8b855a164ebcdf81494a6/Formula/uncrustify.rb > uncrustify.rb && brew install uncrustify.rb && rm uncrustify.rb
```
Code spell checking
===================
Code spell checking is done using [codespell](https://github.com/codespell-project/codespell#codespell)
and runs in a GitHub action in CI. Codespell is configured via `pyproject.toml`
to avoid false positives. It is recommended run codespell before submitting a
PR. To simplify this, codespell is configured as a pre-commit hook and will be
installed if you run `pre-commit install` (see below).
If you want to install and run codespell manually, you can do so by running:
```
$ pip install codespell tomli
$ codespell
```
Automatic Pre-Commit Hooks
==========================

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2013-2024 Damien P. George
Copyright (c) 2013-2023 Damien P. George
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -48,14 +48,12 @@ 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)

View File

@@ -68,7 +68,7 @@ master_doc = "index"
# General information about the project.
project = "MicroPython"
copyright = "- The MicroPython Documentation is Copyright © 2014-2024, Damien P. George, Paul Sokolovsky, and contributors"
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

View File

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

View File

@@ -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.
>>>

View File

@@ -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 },

View File

@@ -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) {

View File

@@ -33,7 +33,7 @@ Variables
MicroPython processes local and global variables differently. Global variables
are stored and looked up from a global dictionary that is allocated on the heap
(note that each module has its own separate dict, so separate namespace).
Local variables on the other hand are stored on the Python value stack, which may
Local variables on the other hand are are stored on the Python value stack, which may
live on the C stack or on the heap. They are accessed directly by their offset
within the Python stack, which is more efficient than a global lookup in a dict.

View File

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

View File

@@ -1,33 +0,0 @@
.. Preamble section inserted into generated output
Positional-only Parameters
--------------------------
To save code size, many functions that accept keyword arguments in CPython only accept positional arguments in MicroPython.
MicroPython marks positional-only parameters in the same way as CPython, by inserting a ``/`` to mark the end of the positional parameters. Any function whose signature ends in ``/`` takes *only* positional arguments. For more details, see `PEP 570 <https://peps.python.org/pep-0570/>`_.
Example
~~~~~~~
For example, in CPython 3.4 this is the signature of the constructor ``socket.socket``::
socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)
However, the signature documented in :func:`MicroPython<socket.socket>` is::
socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, /)
The ``/`` at the end of the parameters indicates that they are all positional-only in MicroPython. The following code works in CPython but not in most MicroPython ports::
import socket
s = socket.socket(type=socket.SOCK_DGRAM)
MicroPython will raise an exception::
TypeError: function doesn't take keyword arguments
The following code will work in both CPython and MicroPython::
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

View File

@@ -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.

View File

@@ -18,9 +18,6 @@ working with this board it may be useful to get an overview of the microcontroll
general.rst
tutorial/index.rst
Note that there are several varieties of ESP32 -- ESP32, ESP32C3, ESP32S2, ESP32S3 --
supported by MicroPython, with some differences in functionality between them.
Installing MicroPython
----------------------
@@ -61,18 +58,12 @@ The :mod:`esp32` module::
import esp32
esp32.raw_temperature() # read the internal temperature of the MCU, in Fahrenheit
esp32.ULP() # access to the Ultra-Low-Power Co-processor, not on ESP32C3
esp32.ULP() # access to the Ultra-Low-Power Co-processor
Note that the temperature sensor in the ESP32 will typically read higher than
ambient due to the IC getting warm while it runs. This effect can be minimised
by reading the temperature sensor immediately after waking up from sleep.
ESP32C3, ESP32S2, and ESP32S3 also have an internal temperature sensor available.
It is implemented a bit differently to the ESP32 and returns the temperature in
Celsius::
esp32.mcu_temperature() # read the internal temperature of the MCU, in Celsius
Networking
----------
@@ -137,7 +128,6 @@ 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
@@ -660,15 +650,15 @@ SD card
See :ref:`machine.SDCard <machine.SDCard>`. ::
import machine, os, vfs
import machine, os
# Slot 2 uses pins sck=18, cs=5, miso=19, mosi=23
sd = machine.SDCard(slot=2)
vfs.mount(sd, '/sd') # mount
os.mount(sd, '/sd') # mount
os.listdir('/sd') # list directory contents
vfs.umount('/sd') # eject
os.umount('/sd') # eject
RMT
---

View File

@@ -149,7 +149,8 @@ class ThreadSafeFlag
Create a new flag which can be used to synchronise a task with code running
outside the asyncio loop, such as other threads, IRQs, or scheduler
callbacks. Flags start in the cleared state.
callbacks. Flags start in the cleared state. The class does not currently
work under the Unix build of MicroPython.
.. method:: ThreadSafeFlag.set()

View File

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

View File

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

View File

@@ -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:`vfs.AbstractBlockDev`.
:class:`os.AbstractBlockDev`.
.. method:: Partition.set_boot()

View File

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

View File

@@ -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.

View File

@@ -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

View File

@@ -75,21 +75,6 @@ Methods
- ``wake`` specifies the sleep mode from where this interrupt can wake
up the system.
.. method:: RTC.memory([data])
``RTC.memory(data)`` will write *data* to the RTC memory, where *data* is any
object which supports the buffer protocol (including `bytes`, `bytearray`,
`memoryview` and `array.array`). ``RTC.memory()`` reads RTC memory and returns
a `bytes` object.
Data written to RTC user memory is persistent across restarts, including
`machine.soft_reset()` and `machine.deepsleep()`.
The maximum length of RTC user memory is 2048 bytes by default on esp32,
and 492 bytes on esp8266.
Availability: esp32, esp8266 ports.
Constants
---------

View File

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

View File

@@ -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:`vfs.AbstractBlockDev`.
The class implements the block protocol defined by :class:`os.AbstractBlockDev`.
This allows the mounting of an SD card to be as simple as::
vfs.mount(machine.SDCard(), "/sd")
os.mount(machine.SDCard(), "/sd")
The constructor takes the following parameters:

View File

@@ -1,296 +0,0 @@
.. 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.
.. warning:: This low-level API assumes familiarity with the USB standard. There
are high-level `usb driver modules in micropython-lib`_ which provide a
simpler interface and more built-in functionality.
Terminology
-----------
- A "Runtime" USB device interface or driver is one which is defined using this
Python API after MicroPython initially starts up.
- A "Built-in" USB device interface or driver is one that is compiled into the
MicroPython firmware, and is always available. Examples are USB-CDC (serial
port) which is usually enabled by default. Built-in USB-MSC (Mass Storage) is an
option on some ports.
Lifecycle
---------
Managing a runtime USB interface can be tricky, especially if you are communicating
with MicroPython over a built-in USB-CDC serial port that's part of the same USB
device.
- A MicroPython 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. Data in this memoryview will be the same
across each of the three stages of a single transfer.
A successful transfer consists of this callback being called in sequence
for the three stages. Generally speaking, if a device wants to do
something in response to a control request then it's best to wait until
the ACK stage to confirm the host controller completed the transfer as
expected.
The callback should return one of the following values:
- ``False`` to stall the endpoint and reject the transfer. It won't
proceed to any remaining stages.
- ``True`` to continue the transfer to the next stage.
- A buffer object can be returned at the SETUP stage when the transfer
will send or receive additional data. Typically this is the case when
the ``wLength`` field in the request has a non-zero value. This should
be a writable buffer for an ``OUT`` direction transfer, or a readable
buffer with data for an ``IN`` direction transfer.
- ``xfer_cb`` - This callback is called whenever a non-control
transfer submitted by calling :func:`USBDevice.submit_xfer` completes.
The callback has three arguments:
1. The Endpoint number for the completed transfer.
2. Result value: ``True`` if the transfer succeeded, ``False``
otherwise.
3. Number of bytes successfully transferred. In the case of a
"short" transfer, The result is ``True`` and ``xferred_bytes``
will be smaller than the length of the buffer submitted for the
transfer.
.. note:: If a bus reset occurs (see :func:`USBDevice.reset`),
``xfer_cb`` is not called for any transfers that have not
already completed.
.. method:: USBDevice.active(self, [value] /)
Returns the current active state of this runtime USB device as a
boolean. The runtime USB device is "active" when it is available to
interact with the host, it doesn't mean that a USB Host is actually
present.
If the optional ``value`` argument is set to a truthy value, then
the USB device will be activated.
If the optional ``value`` argument is set to a falsey value, then
the USB device is deactivated. While the USB device is deactivated,
it will not be detected by the USB Host.
To simulate a disconnect and a reconnect of the USB device, call
``active(False)`` followed by ``active(True)``. This may be
necessary if the runtime device configuration has changed, so that
the host sees the new device.
.. attribute:: USBDevice.builtin_driver
This attribute holds the current built-in driver configuration, and must be
set to one of the ``USBDevice.BUILTIN_`` named constants defined on this object.
By default it holds the value :data:`USBDevice.BUILTIN_NONE`.
Runtime USB device must be inactive when setting this field. Call the
:func:`USBDevice.active` function to deactivate before setting if necessary
(and again to activate after setting).
If this value is set to any value other than :data:`USBDevice.BUILTIN_NONE` then
the following restrictions apply to the :func:`USBDevice.config` arguments:
- ``desc_cfg`` should begin with the built-in USB interface descriptor data
accessible via :data:`USBDevice.builtin_driver` attribute ``desc_cfg``.
Descriptors appended after the built-in configuration descriptors should use
interface, string and endpoint numbers starting from the max built-in values
defined in :data:`USBDevice.builtin_driver` attributes ``itf_max``, ``str_max`` and
``ep_max``.
- The ``bNumInterfaces`` field in the built-in configuration
descriptor will also need to be updated if any new interfaces
are appended to the end of ``desc_cfg``.
- ``desc_strs`` should either be ``None`` or a list/dictionary where index
values less than ``USBDevice.builtin_driver.str_max`` are missing or have
value ``None``. This reserves those string indexes for the built-in
drivers. Placing a different string at any of these indexes overrides that
string in the built-in driver.
.. method:: USBDevice.submit_xfer(self, ep, buffer /)
Submit a USB transfer on endpoint number ``ep``. ``buffer`` must be
an object implementing the buffer interface, with read access for
``IN`` endpoints and write access for ``OUT`` endpoints.
.. note:: ``ep`` cannot be the control Endpoint number 0. Control
transfers are built up through successive executions of
``control_xfer_cb``, see above.
Returns ``True`` if successful, ``False`` if the transfer could not
be queued (as USB device is not configured by host, or because
another transfer is queued on this endpoint.)
When the USB host completes the transfer, the ``xfer_cb`` callback
is called (see above).
Raises ``OSError`` with reason ``MP_EINVAL`` If the USB device is not
active.
.. method:: USBDevice.stall(self, ep, [stall] /)
Calling this function gets or sets the STALL state of a device endpoint.
``ep`` is the number of the endpoint.
If the optional ``stall`` parameter is set, this is a boolean flag
for the STALL state.
The return value is the current stall state of the endpoint (before
any change made by this function).
An endpoint that is set to STALL may remain stalled until this
function is called again, or STALL may be cleared automatically by
the USB host.
Raises ``OSError`` with reason ``MP_EINVAL`` If the USB device is not
active.
Constants
---------
.. data:: USBDevice.BUILTIN_NONE
.. data:: USBDevice.BUILTIN_DEFAULT
.. data:: USBDevice.BUILTIN_CDC
.. data:: USBDevice.BUILTIN_MSC
.. data:: USBDevice.BUILTIN_CDC_MSC
These constant objects hold the built-in descriptor data which is
compiled into the MicroPython firmware. ``USBDevice.BUILTIN_NONE`` and
``USBDevice.BUILTIN_DEFAULT`` are always present. Additional objects may be present
depending on the firmware build configuration and the actual built-in drivers.
.. note:: Currently at most one of ``USBDevice.BUILTIN_CDC``,
``USBDevice.BUILTIN_MSC`` and ``USBDevice.BUILTIN_CDC_MSC`` is defined
and will be the same object as ``USBDevice.BUILTIN_DEFAULT``.
These constants are defined to allow run-time detection of
the built-in driver (if any). Support for selecting one of
multiple built-in driver configurations may be added in the
future.
These values are assigned to :data:`USBDevice.builtin_driver` to get/set the
built-in configuration.
Each object contains the following read-only fields:
- ``itf_max`` - One more than the highest bInterfaceNumber value used
in the built-in configuration descriptor.
- ``ep_max`` - One more than the highest bEndpointAddress value used
in the built-in configuration descriptor. Does not include any
``IN`` flag bit (0x80).
- ``str_max`` - One more than the highest string descriptor index
value used by any built-in descriptor.
- ``desc_dev`` - ``bytes`` object containing the built-in USB device
descriptor.
- ``desc_cfg`` - ``bytes`` object containing the complete built-in USB
configuration descriptor.
.. _usb driver modules in micropython-lib: https://github.com/micropython/micropython-lib/tree/master/micropython/usb#readme

View File

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

View File

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

View File

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

View File

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

View File

@@ -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:`vfs.mount` and :meth:`vfs.umount` instead.
be performed by :meth:`os.mount` and :meth:`os.umount` instead.
Mount a block device and make it available as part of the filesystem.
``device`` must be an object that provides the block protocol. (The
following is also deprecated. See :class:`vfs.AbstractBlockDev` for the
following is also deprecated. See :class:`os.AbstractBlockDev` for the
correct way to create a block device.)
- ``readblocks(self, blocknum, buf)``

View File

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

View File

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

View File

@@ -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
reused so as to save on instruction memory.
re-used 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,10 +140,3 @@ 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.

View File

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

View File

@@ -13,7 +13,7 @@ facilities for network sockets, both client-side and server-side.
Functions
---------
.. function:: ssl.wrap_socket(sock, server_side=False, key=None, cert=None, cert_reqs=CERT_NONE, cadata=None, server_hostname=None, do_handshake=True)
.. function:: ssl.wrap_socket(sock, server_side=False, keyfile=None, certfile=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`

View File

@@ -45,8 +45,6 @@ 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 |

View File

@@ -69,7 +69,7 @@ Constants
MicroPython, it has following attributes:
* *name* - string "micropython"
* *version* - tuple (major, minor, micro, releaselevel), e.g. (1, 22, 0, '')
* *version* - tuple (major, minor, micro), e.g. (1, 7, 0)
* *_machine* - string describing the underlying machine
* *_mpy* - supported mpy file-format version (optional attribute)
@@ -77,9 +77,6 @@ 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

View File

@@ -1,208 +0,0 @@
: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.

View File

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

View File

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

View File

@@ -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"

View File

@@ -309,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:
@@ -443,27 +443,27 @@ SD card
See :ref:`machine.SDCard <machine.SDCard>`::
import machine, os, vfs
import machine, os
sd = machine.SDCard()
fs = vfs.VfsFat(sd)
vfs.mount(fs, "/sd") # mount
fs = os.VfsFat(sd)
os.mount(fs, "/sd") # mount
os.listdir('/sd') # list directory contents
vfs.umount('/sd') # eject
os.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 vfs, sdcard, machine
import os, 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)
fs = vfs.VfsFat(sd)
vfs.mount(fs, "/sdcard")
vfs = os.VfsFat(sd)
os.mount(vfs, "/sdcard")
OneWire driver
--------------

View File

@@ -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 ``vfs.mount``).
mount and use it later in your program using ``os.mount``).
(Note that on older versions of the board, ``/flash`` is called ``0:/`` and ``/sd``
is called ``1:/``).

View File

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

View File

@@ -40,7 +40,7 @@ Block devices
-------------
A block device is an instance of a class that implements the
:class:`vfs.AbstractBlockDev` protocol.
:class:`os.AbstractBlockDev` protocol.
Built-in block devices
~~~~~~~~~~~~~~~~~~~~~~
@@ -108,16 +108,16 @@ RAM using a ``bytearray``::
It can be used as follows::
import vfs
import os
bdev = RAMBlockDev(512, 50)
vfs.VfsFat.mkfs(bdev)
vfs.mount(bdev, '/ramdisk')
os.VfsFat.mkfs(bdev)
os.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:`vfs.AbstractBlockDev.readblocks` and
:meth:`vfs.AbstractBlockDev.writeblocks` methods) is::
:meth:`os.AbstractBlockDev.readblocks` and
:meth:`os.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
<vfs.VfsLfs2>`::
<os.VfsLfs2>`::
import vfs
import os
bdev = RAMBlockDev(512, 50)
vfs.VfsLfs2.mkfs(bdev)
vfs.mount(bdev, '/ramdisk')
os.VfsLfs2.mkfs(bdev)
os.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 <vfs.VfsFat>`,
:class:`littlefs v1 <vfs.VfsLfs1>` and :class:`littlefs v2 <vfs.VfsLfs2>`.
MicroPython ports can provide implementations of :class:`FAT <os.VfsFat>`,
:class:`littlefs v1 <os.VfsLfs1>` and :class:`littlefs v2 <os.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 vfs
vfs.umount('/')
vfs.VfsFat.mkfs(bdev)
vfs.mount(bdev, '/')
import os
os.umount('/')
os.VfsFat.mkfs(bdev)
os.mount(bdev, '/')
# STM32
import os, vfs, pyb
vfs.umount('/flash')
vfs.VfsFat.mkfs(pyb.Flash(start=0))
vfs.mount(pyb.Flash(start=0), '/flash')
import os, pyb
os.umount('/flash')
os.VfsFat.mkfs(pyb.Flash(start=0))
os.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 vfs
vfs.umount('/')
vfs.VfsLfs2.mkfs(bdev)
vfs.mount(bdev, '/')
import os
os.umount('/')
os.VfsLfs2.mkfs(bdev)
os.mount(bdev, '/')
# STM32
import os, vfs, pyb
vfs.umount('/flash')
vfs.VfsLfs2.mkfs(pyb.Flash(start=0))
vfs.mount(pyb.Flash(start=0), '/flash')
import os, pyb
os.umount('/flash')
os.VfsLfs2.mkfs(pyb.Flash(start=0))
os.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, vfs, pyb
vfs.umount('/flash')
import os, pyb
os.umount('/flash')
p1 = pyb.Flash(start=0, len=256*1024)
p2 = pyb.Flash(start=256*1024)
vfs.VfsFat.mkfs(p1)
vfs.VfsLfs2.mkfs(p2)
vfs.mount(p1, '/flash')
vfs.mount(p2, '/data')
os.VfsFat.mkfs(p1)
os.VfsLfs2.mkfs(p2)
os.mount(p1, '/flash')
os.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 vfs, pyb
import os, pyb
p2 = pyb.Flash(start=256*1024)
vfs.mount(p2, '/data')
os.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, vfs
import esp32, os
p = esp32.Partition.find(esp32.Partition.TYPE_DATA, label='foo')
vfs.mount(p, '/foo')
os.mount(p, '/foo')

View File

@@ -95,17 +95,6 @@ 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
@@ -149,13 +138,11 @@ See :func:`micropython.opt_level`.
You can use the variables above, such as ``$(PORT_DIR)`` in ``base_path``.
.. function:: require(name, library=None)
.. function:: require(name, unix_ffi=False)
Require a package by name (and its dependencies) from :term:`micropython-lib`.
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.
Optionally specify unix_ffi=True to use a module from the unix-ffi directory.
.. function:: include(manifest_path)

View File

@@ -71,11 +71,4 @@ 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`
*None yet*

View File

@@ -682,13 +682,6 @@ See :ref:`packages`.
Install the package from the specified branch at org/repo on GitHub to the
device. See :ref:`packages`.
.. code-block:: bash
mpremote mip install gitlab:org/repo@branch
Install the package from the specified branch at org/repo on GitLab to the
device. See :ref:`packages`.
.. code-block:: bash
mpremote mip install --target /flash/third-party functools

View File

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

View File

@@ -7,7 +7,7 @@ Installing packages with ``mip``
--------------------------------
Network-capable boards include the ``mip`` module, which can install packages
from :term:`micropython-lib` and from third-party sites (including GitHub, GitLab).
from :term:`micropython-lib` and from third-party sites (including GitHub).
``mip`` ("mip installs packages") is similar in concept to Python's ``pip`` tool,
however it does not use the PyPI index, rather it uses :term:`micropython-lib`
@@ -38,28 +38,24 @@ install third-party libraries. The simplest way is to download a file directly::
When installing a file directly, the ``target`` argument is still supported to set
the destination path, but ``mpy`` and ``version`` are ignored.
The URL can also start with ``github:`` or ``gitlab:`` as a simple way of pointing to content
hosted on GitHub or GitLab::
The URL can also start with ``github:`` as a simple way of pointing to content
hosted on GitHub::
>>> mip.install("github:org/repo/path/foo.py") # Uses default branch
>>> mip.install("github:org/repo/path/foo.py", version="branch-or-tag") # Optionally specify the branch or tag
>>> mip.install("gitlab:org/repo/path/foo.py") # Uses default branch
>>> mip.install("gitlab:org/repo/path/foo.py", version="branch-or-tag") # Optionally specify the branch or tag
More sophisticated packages (i.e. with more than one file, or with dependencies)
can be downloaded by specifying the path to their ``package.json``.
>>> mip.install("http://example.com/x/package.json")
>>> mip.install("github:org/user/path/package.json")
>>> mip.install("gitlab:org/user/path/package.json")
If no json file is specified, then "package.json" is implicitly added::
>>> mip.install("http://example.com/x/")
>>> mip.install("github:org/repo") # Uses default branch of that repo
>>> mip.install("github:org/repo", version="branch-or-tag")
>>> mip.install("gitlab:org/repo") # Uses default branch of that repo
>>> mip.install("gitlab:org/repo", version="branch-or-tag")
Using ``mip`` on the Unix port
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -87,8 +83,6 @@ can be used from a host PC to install packages to a locally connected device
$ mpremote mip install http://example.com/x/y/foo.py
$ mpremote mip install github:org/repo
$ mpremote mip install github:org/repo@branch-or-tag
$ mpremote mip install gitlab:org/repo
$ mpremote mip install gitlab:org/repo@branch-or-tag
The ``--target=path``, ``--no-mpy``, and ``--index`` arguments can be set::
@@ -126,8 +120,7 @@ A typical ``package.json`` for an example ``mlx90640`` library looks like::
"deps": [
["collections-defaultdict", "latest"],
["os-path", "latest"],
["github:org/micropython-additions", "main"],
["gitlab:org/micropython-otheradditions", "main"]
["github:org/micropython-additions", "main"]
],
"version": "0.2"
}

View File

@@ -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, vfs, sdcard
import os, sdcard
spi = SPI(0, baudrate=500000)
cs = Pin.cpu.P103
sd = sdcard.SDCard(spi, cs)
vfs.mount(sd, '/sd')
os.mount(sd, '/sd')
os.listdir('/')
os.chdir('/sd')
vfs.umount('/sd')
os.umount('/sd')
OneWire driver
--------------

View File

@@ -17,12 +17,12 @@ Adafruit ItsyBitsy M0 Express pin assignment table
=== ==== ============ ==== ==== ====== ====== ====== ======
Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC
=== ==== ============ ==== ==== ====== ====== ====== ======
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 -
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
@@ -30,31 +30,31 @@ Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC
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 -
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 -
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 -
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 -
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 - - - - -
28 PA28 8 - - - - -
=== ==== ============ ==== ==== ====== ====== ====== ======
@@ -348,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
@@ -364,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
@@ -383,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
=== ==== ============ ==== ==== ==== ====== ====== ===== ===== =====
@@ -870,7 +870,7 @@ Adafruit ItsyBitsy M4 Express :ref:`samd51_pinout_table`.
The default devices at the board are:
- UART 2 at pins PA13/PA12, labelled RXD/TXD
- UART 1 at pins PB23/PB22, 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
@@ -884,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_item(e, txt):
def print_entry(e, txt):
print(txt, end=": ")
if e == 255:
print(" - ", end="")
else:
print("%d/%d" % (e >> 4, e & 0x0f), end="")
def print_pininfo(pin_id, name, info):
print("%3d" % pin_id, end=" ")
print("%4s %12s" % (info[0], name), 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="")
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_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")
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")
else:
print(" ADC1:%2s" % (info[3] if info[3] != 255 else "-"), end="")
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_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()
def tblkey(i):
name = i[1]
if name != "":
name = i[1][0]
if name != "-":
if len(name) < 3:
return " " + name
else:
@@ -921,25 +921,17 @@ 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, sort=True):
def table(num = 127):
pintbl = []
inv_bd = {v: k for k, v in Pin.board.__dict__.items()}
for i in range(num):
try:
p = Pin(i)
pi = pininfo(p)
if p in inv_bd.keys():
name = inv_bd[p]
else:
name = ""
pintbl.append((i, name, pininfo(i)))
pintbl.append((i, pininfo(i)))
except:
pass
# print("not defined")
if sort:
pintbl.sort(key=tblkey)
pintbl.sort(key=tblkey)
for item in pintbl:
print_pininfo(item[0], item[1], item[2])
print_pininfo(item[0], item[1])
table()

View File

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

View File

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

View File

@@ -109,12 +109,12 @@ Disk Access
Use the :ref:`zephyr.DiskAccess <zephyr.DiskAccess>` class to support filesystem::
import vfs
import os
from zephyr import DiskAccess
block_dev = DiskAccess('SDHC') # create a block device object for an SD card
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
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
# 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 vfs
import os
from zephyr import FlashArea
block_dev = FlashArea(4, 4096) # creates a block device object in the frdm-k64f flash scratch partition
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
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
# 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

View File

@@ -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 `vfs Filesystem Mounting <https://docs.micropython.org/en/latest/library/vfs.html?highlight=vfs#filesystem-mounting>`_.
See `os Filesystem Mounting <https://docs.micropython.org/en/latest/library/os.html?highlight=os#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 `vfs.AbstractBlockDev` protocol.
implements the `os.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 vfs
import os
from zephyr import DiskAccess
bdev = zephyr.DiskAccess('SDHC') # create block device object using DiskAccess
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
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
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 `vfs.AbstractBlockDev` protocol.
implements the `os.AbstractBlockDev` protocol.
Example usage with the internal flash on the reel_board or the rv32m1_vega_ri5cy board::
import vfs
import os
from zephyr import FlashArea
bdev = FlashArea(FlashArea.STORAGE, 4096) # create block device object using FlashArea
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
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
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

View File

@@ -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);

View File

@@ -51,7 +51,7 @@ extern uint8_t mp_bluetooth_hci_cmd_buf[4 + 256];
// Provided by the port.
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,7 +64,7 @@ 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) {
@@ -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) {

View File

@@ -29,9 +29,6 @@
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#if MICROPY_PY_MACHINE_PULSE
#include "extmod/modmachine.h"
#include "drivers/dht/dht.h"
@@ -40,7 +37,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);
@@ -95,5 +92,3 @@ timeout:
mp_raise_OSError(MP_ETIMEDOUT);
}
MP_DEFINE_CONST_FUN_OBJ_2(dht_readinto_obj, dht_readinto);
#endif // MICROPY_PY_MACHINE_PULSE

View File

@@ -44,14 +44,14 @@
extern void mod_network_poll_events(void);
static mp_obj_t esp_hosted_pin_irq_callback(mp_obj_t self_in) {
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.

View File

@@ -442,23 +442,6 @@ typedef struct {
.single_status_byte = false, \
}
// Settings for the ISSI devices
#define IS25LPWP064D { \
.total_size = (1 << 23), /* 8 MiB */ \
.start_up_time_us = 5000, \
.manufacturer_id = 0x9D, \
.memory_type = 0x60, \
.capacity = 0x17, \
.max_clock_speed_mhz = 80, \
.quad_enable_bit_mask = 0x40, \
.has_sector_protection = false, \
.supports_fast_read = true, \
.supports_qspi = true, \
.supports_qspi_writes = true, \
.write_status_register_split = false, \
.single_status_byte = true, \
}
// Settings for a GENERIC device with the most common setting
#define GENERIC { \
.total_size = (1 << 21), /* 2 MiB */ \

View File

@@ -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;

View File

@@ -12,7 +12,7 @@ PROG = embed
CFLAGS += -I.
CFLAGS += -I$(EMBED_DIR)
CFLAGS += -I$(EMBED_DIR)/port
CFLAGS += -Wall -Og -fno-common
CFLAGS += -Wall -Og
SRC += main.c
SRC += $(wildcard $(EMBED_DIR)/*/*.c) $(wildcard $(EMBED_DIR)/*/*/*.c)

View File

@@ -31,14 +31,7 @@ static char heap[8 * 1024];
int main() {
// Initialise MicroPython.
//
// Note: &stack_top below should be good enough for many cases.
// However, depending on environment, there might be more appropriate
// ways to get the stack top value.
// eg. pthread_get_stackaddr_np, pthread_getattr_np,
// __builtin_frame_address/__builtin_stack_address, etc.
int stack_top;
mp_embed_init(&heap[0], sizeof(heap), &stack_top);
mp_embed_init(&heap[0], sizeof(heap));
// Run the example scripts (they will be compiled first).
mp_embed_exec_str(example_1);

View File

@@ -5,16 +5,15 @@ MPY_DIR = ../../..
MOD = btree_$(ARCH)
# Source files (.c or .py)
SRC = btree_c.c
SRC = btree_c.c btree_py.py
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
ARCH = x64
BTREE_DIR = $(MPY_DIR)/lib/berkeley-db-1.xx
BERKELEY_DB_CONFIG_FILE ?= \"extmod/berkeley-db/berkeley_db_config_port.h\"
CFLAGS += -I$(BTREE_DIR)/include
CFLAGS += -DBERKELEY_DB_CONFIG_FILE=$(BERKELEY_DB_CONFIG_FILE)
CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter
BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error="(void)" -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA)
CFLAGS += -I$(BTREE_DIR)/PORT/include
CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS)
SRC += $(addprefix $(realpath $(BTREE_DIR))/,\
btree/bt_close.c \

View File

@@ -39,10 +39,6 @@ void abort_(void) {
nlr_raise(mp_obj_new_exception(mp_load_global(MP_QSTR_RuntimeError)));
}
int puts(const char *s) {
return mp_printf(&mp_plat_print, "%s\n", s);
}
int native_errno;
#if defined(__linux__)
int *__errno_location (void)
@@ -104,41 +100,25 @@ mp_getiter_iternext_custom_t btree_getiter_iternext;
#include "extmod/modbtree.c"
mp_map_elem_t btree_locals_dict_table[8];
static MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table);
static mp_obj_t btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// The allowed_args array must have its qstr's populated at runtime.
enum { ARG_flags, ARG_cachesize, ARG_pagesize, ARG_minkeypage };
mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
};
allowed_args[0].qst = MP_QSTR_flags;
allowed_args[1].qst = MP_QSTR_cachesize;
allowed_args[2].qst = MP_QSTR_pagesize;
allowed_args[3].qst = MP_QSTR_minkeypage;
STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table);
STATIC mp_obj_t btree_open(size_t n_args, const mp_obj_t *args) {
// Make sure we got a stream object
mp_get_stream_raise(pos_args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
BTREEINFO openinfo = {0};
openinfo.flags = args[ARG_flags].u_int;
openinfo.cachesize = args[ARG_cachesize].u_int;
openinfo.psize = args[ARG_pagesize].u_int;
openinfo.minkeypage = args[ARG_minkeypage].u_int;
DB *db = __bt_open(MP_OBJ_TO_PTR(pos_args[0]), &btree_stream_fvtable, &openinfo, 0);
openinfo.flags = mp_obj_get_int(args[1]);
openinfo.cachesize = mp_obj_get_int(args[2]);
openinfo.psize = mp_obj_get_int(args[3]);
openinfo.minkeypage = mp_obj_get_int(args[4]);
DB *db = __bt_open(MP_OBJ_TO_PTR(args[0]), &btree_stream_fvtable, &openinfo, 0);
if (db == NULL) {
mp_raise_OSError(native_errno);
}
return MP_OBJ_FROM_PTR(btree_new(db, pos_args[0]));
return MP_OBJ_FROM_PTR(btree_new(db, args[0]));
}
static MP_DEFINE_CONST_FUN_OBJ_KW(btree_open_obj, 1, btree_open);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_open_obj, 5, 5, btree_open);
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY
@@ -163,7 +143,7 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
btree_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_items), MP_OBJ_FROM_PTR(&btree_items_obj) };
MP_OBJ_TYPE_SET_SLOT(&btree_type, locals_dict, (void*)&btree_locals_dict, 4);
mp_store_global(MP_QSTR_open, MP_OBJ_FROM_PTR(&btree_open_obj));
mp_store_global(MP_QSTR__open, MP_OBJ_FROM_PTR(&btree_open_obj));
mp_store_global(MP_QSTR_INCL, MP_OBJ_NEW_SMALL_INT(FLAG_END_KEY_INCL));
mp_store_global(MP_QSTR_DESC, MP_OBJ_NEW_SMALL_INT(FLAG_DESC));

View File

@@ -0,0 +1,7 @@
# Implemented in Python to support keyword arguments
# ruff: noqa: F821 - this file is evaluated with C-defined names in scope
def open(stream, *, flags=0, cachesize=0, pagesize=0, minkeypage=0):
return _open(stream, flags, cachesize, pagesize, minkeypage)

View File

@@ -29,7 +29,7 @@ mp_obj_t mp_stream_close(mp_obj_t stream) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_close_obj, mp_stream_close);
// Re-implemented from py/stream.c, not yet available in dynruntime.h.
static mp_obj_t mp_stream___exit__(size_t n_args, const mp_obj_t *args) {
STATIC mp_obj_t mp_stream___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
return mp_stream_close(args[0]);
}
@@ -42,7 +42,7 @@ mp_obj_t mp_identity(mp_obj_t self) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity);
mp_map_elem_t deflateio_locals_dict_table[7];
static MP_DEFINE_CONST_DICT(deflateio_locals_dict, deflateio_locals_dict_table);
STATIC MP_DEFINE_CONST_DICT(deflateio_locals_dict, deflateio_locals_dict_table);
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY

View File

@@ -8,7 +8,7 @@
#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;
}
@@ -16,7 +16,7 @@ static mp_int_t factorial_helper(mp_int_t x) {
}
// This is the function which will be called from Python, as factorial(x)
static mp_obj_t factorial(mp_obj_t x_obj) {
STATIC mp_obj_t factorial(mp_obj_t x_obj) {
// Extract the integer from the MicroPython input object
mp_int_t x = mp_obj_get_int(x_obj);
// Calculate the factorial
@@ -25,7 +25,7 @@ static mp_obj_t factorial(mp_obj_t x_obj) {
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) {

View File

@@ -25,15 +25,15 @@ uint16_t *const table_ptr16a[] = { &data16[0], &data16[1], &data16[2], &data16[3
const uint16_t *const table_ptr16b[] = { &table16[0], &table16[1] };
// A simple function that adds its 2 arguments (must be integers)
static mp_obj_t add(mp_obj_t x_in, mp_obj_t y_in) {
STATIC mp_obj_t add(mp_obj_t x_in, mp_obj_t y_in) {
mp_int_t x = mp_obj_get_int(x_in);
mp_int_t y = mp_obj_get_int(y_in);
return mp_obj_new_int(x + y);
}
static MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add);
// A local helper function (not exposed to Python)
static mp_int_t fibonacci_helper(mp_int_t x) {
STATIC mp_int_t fibonacci_helper(mp_int_t x) {
if (x < MP_ARRAY_SIZE(table8)) {
return table8[x];
} else {
@@ -42,17 +42,17 @@ static mp_int_t fibonacci_helper(mp_int_t x) {
}
// A function which computes Fibonacci numbers
static mp_obj_t fibonacci(mp_obj_t x_in) {
STATIC mp_obj_t fibonacci(mp_obj_t x_in) {
mp_int_t x = mp_obj_get_int(x_in);
if (x < 0) {
mp_raise_ValueError(MP_ERROR_TEXT("can't compute negative Fibonacci number"));
}
return mp_obj_new_int(fibonacci_helper(x));
}
static MP_DEFINE_CONST_FUN_OBJ_1(fibonacci_obj, fibonacci);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fibonacci_obj, fibonacci);
// A function that accesses the BSS data
static mp_obj_t access(size_t n_args, const mp_obj_t *args) {
STATIC mp_obj_t access(size_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
// Create a list holding all items from data16
mp_obj_list_t *lst = MP_OBJ_TO_PTR(mp_obj_new_list(MP_ARRAY_SIZE(data16), NULL));
@@ -71,17 +71,17 @@ static mp_obj_t access(size_t n_args, const mp_obj_t *args) {
return mp_const_none;
}
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(access_obj, 0, 2, access);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(access_obj, 0, 2, access);
// A function that allocates memory and creates a bytearray
static mp_obj_t make_array(void) {
STATIC mp_obj_t make_array(void) {
uint16_t *ptr = m_new(uint16_t, MP_ARRAY_SIZE(table_ptr16b));
for (int i = 0; i < MP_ARRAY_SIZE(table_ptr16b); ++i) {
ptr[i] = *table_ptr16b[i];
}
return mp_obj_new_bytearray_by_ref(sizeof(uint16_t) * MP_ARRAY_SIZE(table_ptr16b), ptr);
}
static MP_DEFINE_CONST_FUN_OBJ_0(make_array_obj, make_array);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(make_array_obj, make_array);
// 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) {

View File

@@ -22,29 +22,29 @@
// A function that uses the default float type configured for the current target
// This default can be overridden by specifying MICROPY_FLOAT_IMPL at the make level
static mp_obj_t add(mp_obj_t x, mp_obj_t y) {
STATIC mp_obj_t add(mp_obj_t x, mp_obj_t y) {
return mp_obj_new_float(mp_obj_get_float(x) + mp_obj_get_float(y));
}
static MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add);
// A function that explicitly uses single precision floats
static mp_obj_t add_f(mp_obj_t x, mp_obj_t y) {
STATIC mp_obj_t add_f(mp_obj_t x, mp_obj_t y) {
return mp_obj_new_float_from_f(mp_obj_get_float_to_f(x) + mp_obj_get_float_to_f(y));
}
static MP_DEFINE_CONST_FUN_OBJ_2(add_f_obj, add_f);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_f_obj, add_f);
#if USE_DOUBLE
// A function that explicitly uses double precision floats
static mp_obj_t add_d(mp_obj_t x, mp_obj_t y) {
STATIC mp_obj_t add_d(mp_obj_t x, mp_obj_t y) {
return mp_obj_new_float_from_d(mp_obj_get_float_to_d(x) + mp_obj_get_float_to_d(y));
}
static MP_DEFINE_CONST_FUN_OBJ_2(add_d_obj, add_d);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_d_obj, add_d);
#endif
// A function that computes the product of floats in an array.
// This function uses the most general C argument interface, which is more difficult
// to use but has access to the globals dict of the module via self->globals.
static mp_obj_t productf(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
STATIC mp_obj_t productf(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
// Check number of arguments is valid
mp_arg_check_num(n_args, n_kw, 1, 1, false);

View File

@@ -8,7 +8,7 @@
#include "py/dynruntime.h"
// A function that returns a tuple of object types.
static mp_obj_t get_types(void) {
STATIC mp_obj_t get_types(void) {
return mp_obj_new_tuple(9, ((mp_obj_t []) {
MP_OBJ_FROM_PTR(&mp_type_type),
MP_OBJ_FROM_PTR(&mp_type_NoneType),
@@ -21,10 +21,10 @@ static mp_obj_t get_types(void) {
MP_OBJ_FROM_PTR(&mp_type_dict),
}));
}
static MP_DEFINE_CONST_FUN_OBJ_0(get_types_obj, get_types);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(get_types_obj, get_types);
// A function that returns a tuple of constant objects.
static mp_obj_t get_const_objects(void) {
STATIC mp_obj_t get_const_objects(void) {
return mp_obj_new_tuple(5, ((mp_obj_t []) {
mp_const_none,
mp_const_false,
@@ -33,17 +33,17 @@ static mp_obj_t get_const_objects(void) {
mp_const_empty_tuple,
}));
}
static MP_DEFINE_CONST_FUN_OBJ_0(get_const_objects_obj, get_const_objects);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(get_const_objects_obj, get_const_objects);
// A function that creates a dictionary from the given arguments.
static mp_obj_t make_dict(size_t n_args, const mp_obj_t *args) {
STATIC mp_obj_t make_dict(size_t n_args, const mp_obj_t *args) {
mp_obj_t dict = mp_obj_new_dict(n_args / 2);
for (; n_args >= 2; n_args -= 2, args += 2) {
mp_obj_dict_store(dict, args[0], args[1]);
}
return dict;
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(make_dict_obj, 0, MP_OBJ_FUN_ARGS_MAX, make_dict);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(make_dict_obj, 0, MP_OBJ_FUN_ARGS_MAX, make_dict);
// 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) {

View File

@@ -1,6 +1,5 @@
/*
This example extends on features0 but demonstrates how to define a class,
and a custom exception.
This example extends on features0 but demonstrates how to define a class.
The Factorial class constructor takes an integer, and then the calculate
method can be called to get the factorial.
@@ -9,9 +8,6 @@
>>> f = features4.Factorial(4)
>>> f.calculate()
24
If the argument to the Factorial class constructor is less than zero, a
FactorialError is raised.
*/
// Include the header file to get access to the MicroPython API
@@ -26,24 +22,18 @@ typedef struct {
mp_int_t n;
} mp_obj_factorial_t;
mp_obj_full_type_t mp_type_FactorialError;
// Essentially Factorial.__new__ (but also kind of __init__).
// Takes a single argument (the number to find the factorial of)
static mp_obj_t factorial_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) {
STATIC mp_obj_t factorial_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) {
mp_arg_check_num(n_args, n_kw, 1, 1, false);
mp_obj_factorial_t *o = mp_obj_malloc(mp_obj_factorial_t, type);
o->n = mp_obj_get_int(args_in[0]);
if (o->n < 0) {
mp_raise_msg((mp_obj_type_t *)&mp_type_FactorialError, "argument must be zero or above");
}
return MP_OBJ_FROM_PTR(o);
}
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;
}
@@ -51,16 +41,16 @@ static mp_int_t factorial_helper(mp_int_t x) {
}
// Implements Factorial.calculate()
static mp_obj_t factorial_calculate(mp_obj_t self_in) {
STATIC mp_obj_t factorial_calculate(mp_obj_t self_in) {
mp_obj_factorial_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_int(factorial_helper(self->n));
}
static MP_DEFINE_CONST_FUN_OBJ_1(factorial_calculate_obj, factorial_calculate);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_calculate_obj, factorial_calculate);
// Locals dict for the Factorial type (will have a single method, calculate,
// added in mpy_init).
mp_map_elem_t factorial_locals_dict_table[1];
static MP_DEFINE_CONST_DICT(factorial_locals_dict, factorial_locals_dict_table);
STATIC MP_DEFINE_CONST_DICT(factorial_locals_dict, factorial_locals_dict_table);
// 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) {
@@ -78,12 +68,6 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
// Make the Factorial type available on the module.
mp_store_global(MP_QSTR_Factorial, MP_OBJ_FROM_PTR(&mp_type_factorial));
// Initialise the exception type.
mp_obj_exception_init(&mp_type_FactorialError, MP_QSTR_FactorialError, &mp_type_Exception);
// Make the FactorialError type available on the module.
mp_store_global(MP_QSTR_FactorialError, MP_OBJ_FROM_PTR(&mp_type_FactorialError));
// This must be last, it restores the globals dict
MP_DYNRUNTIME_INIT_EXIT
}

View File

@@ -1,4 +1,3 @@
#define MICROPY_PY_ARRAY (1)
#define MICROPY_PY_FRAMEBUF (1)
#include "py/dynruntime.h"
@@ -13,8 +12,8 @@ mp_obj_full_type_t mp_type_framebuf;
#include "extmod/modframebuf.c"
mp_map_elem_t framebuf_locals_dict_table[12];
static MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table);
mp_map_elem_t framebuf_locals_dict_table[11];
STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table);
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY
@@ -31,10 +30,9 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
framebuf_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_rect), MP_OBJ_FROM_PTR(&framebuf_rect_obj) };
framebuf_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_line), MP_OBJ_FROM_PTR(&framebuf_line_obj) };
framebuf_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ellipse), MP_OBJ_FROM_PTR(&framebuf_ellipse_obj) };
framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_poly), MP_OBJ_FROM_PTR(&framebuf_poly_obj) };
framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) };
framebuf_locals_dict_table[10] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) };
framebuf_locals_dict_table[11] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) };
framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) };
framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) };
framebuf_locals_dict_table[10] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) };
MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, locals_dict, (void*)&framebuf_locals_dict, 2);
mp_store_global(MP_QSTR_FrameBuffer, MP_OBJ_FROM_PTR(&mp_type_framebuf));

View File

@@ -38,10 +38,10 @@ mp_obj_full_type_t re_type;
#include "extmod/modre.c"
mp_map_elem_t match_locals_dict_table[5];
static MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table);
STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table);
mp_map_elem_t re_locals_dict_table[3];
static MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table);
STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table);
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY

View File

@@ -1,75 +0,0 @@
# Example of a HTTPS client working with non-blocking sockets.
#
# Non-blocking SSL streams works differently in MicroPython compared to CPython. In
# CPython a write to an SSLSocket may raise ssl.SSLWantReadError. In MicroPython an
# SSLSocket behaves like a normal socket/stream and can be polled for reading/writing.
from errno import EINPROGRESS
import select
import socket
import ssl
def connect_nonblocking(sock, addr):
sock.setblocking(False)
try:
sock.connect(addr)
except OSError as er:
if er.errno != EINPROGRESS:
raise er
def write_nonblocking(poller, sock, data):
poller.register(sock, select.POLLOUT)
while data:
poller.poll()
n = sock.write(data)
print("Wrote:", n)
if n is not None:
data = data[n:]
def read_nonblocking(poller, sock, n):
poller.register(sock, select.POLLIN)
poller.poll()
data = sock.read(n)
print("Read:", len(data))
return data
def main(url):
# Split the given URL into components.
proto, _, host, path = url.split(b"/", 3)
assert proto == b"https:"
# Note: this getaddrinfo() call is blocking!
ai = socket.getaddrinfo(host, 443)[0]
addr = ai[-1]
print("Connect address:", addr)
# Create a TCP socket and connect to the server in non-blocking mode.
sock = socket.socket(ai[0], ai[1], ai[2])
connect_nonblocking(sock, addr)
# Wrap the TCP socket in an SSL stream in non-blocking mode.
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
sock = ctx.wrap_socket(sock, server_hostname=host, do_handshake_on_connect=False)
sock.setblocking(False)
# Create an object to poll the SSL stream for readability/writability.
poller = select.poll()
# Send the HTTP request on the SSL stream.
request = b"GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n" % (path, host)
write_nonblocking(poller, sock, request)
# Receive the HTTP response from the SSL stream.
response = read_nonblocking(poller, sock, 1000)
for line in response.split(b"\n"):
print(line)
# Close the SSL stream. This will also close the underlying TCP socket.
sock.close()
main(b"https://micropython.org/ks/test.html")

View File

@@ -1,16 +0,0 @@
## USBDevice Examples
These are examples of how to use the low-level `machine.USBDevice` class to create custom
USB device functionality.
Alternatively, there are [usb driver modules in
micropython-lib](https://github.com/micropython/micropython-lib/tree/master/micropython/usb#readme)
which provide a simpler interface and more built-in functionality.
In this directory:
* `usb_dfu_device.py` implements the USB Device Firmware Update protocol.
* `usb_simple_device.py` implements a custom USB protocol, with a matching host
program to run on a PC.
See comments at the top of each Python file for more details.

View File

@@ -1,327 +0,0 @@
# Implementation of USB DFU device in Python.
#
# To run, just execute this file on a device with machine.USBDevice support. The device
# will then change to DFU mode.
#
# For example, use `mpremote` (the `--no-follow` option starts the script running
# without waiting for a response, because there won't be a response, the USB will change
# to a DFU device):
#
# $ mpremote run --no-follow usb_dfu_device.py
#
# Then you can access the DFU device using the `pydfu.py` script in this repository, to
# list DFU device, copy a file to the device, then exit DFU mode:
#
# $ ../../tools/pydfu.py -l
# $ ../../tools/pydfu.py -u <file.dfu>
#
# After running the last command above, the USB CDC device and REPL should reappear.
import struct, machine
# USB constants for bmRequestType.
USB_REQ_RECIP_INTERFACE = 0x01
USB_REQ_TYPE_CLASS = 0x20
USB_DIR_OUT = 0x00
USB_DIR_IN = 0x80
# String describing the memory layout of the DFU device.
MEMORY_LAYOUT = b"@Internal Flash /0x08000000/16*128Kg"
# VID and PID of the DFU device (these are the ST values).
VID = 0x0483
PID = 0xDF11
# Maximum transfer size for RX and TX.
wTransferSize = 2048
# DFU device descriptor.
_desc_dev = bytes(
[
0x12, # bLength
0x01, # bDescriptorType: Device
0x00,
0x02, # USB version: 2.00
0x00, # bDeviceClass
0x00, # bDeviceSubClass
0x00, # bDeviceProtocol
0x40, # bMaxPacketSize
VID & 0xFF,
VID >> 8, # VID
PID & 0xFF,
PID >> 8, # PID
0x00,
0x01, # bcdDevice: 1.00
0x11, # iManufacturer
0x12, # iProduct
0x13, # iSerialNumber
0x01, # bNumConfigurations: 1
]
)
# DFU configuration descriptor.
_desc_cfg = bytes(
[
# Configuration Descriptor.
0x09, # bLength
0x02, # bDescriptorType
0x1B,
0x00, # wTotalLength: 27
0x01, # bNumInterfaces
0x01, # bConfigurationValue
0x00, # iConfiguration
0x80, # bmAttributes (bus powered)
0x32, # bMaxPower
# Interface Descriptor.
0x09, # bLength
0x04, # bDescriptorType
0x00, # bInterfaceNumber
0x00, # bNumEndpointns
0x00, # bAlternateSetting
0xFE, # bInterfaceClass: application specific interface
0x01, # bInterfaceSubClasse: device firmware update
0x02, # bInterfaceProtocol
0x14, # iInterface
# Device Firmware Upgrade Interface Descriptor.
0x09, # bLength
0x21, # bDescriptorType
0x0B, # bmAttributes (will detach, upload supported, download supported)
0xFF,
0x00, # wDetatchTimeout
wTransferSize & 0xFF,
wTransferSize >> 8, # wTransferSize
0x1A,
0x01, # bcdDFUVersion
]
)
# DFU strings.
_desc_strs = {
0x11: b"iManufacturer",
0x12: b"iProduct",
0x13: b"iSerialNumber",
0x14: MEMORY_LAYOUT,
}
# This class handles the DFU USB device logic.
class DFUOverUSB:
def __init__(self, dfu):
# USB buffer for transfers.
self.usb_buf = bytearray(wTransferSize)
# Instance of the DFU state machine.
self.dfu = dfu
def _control_xfer_cb(self, stage, request):
bmRequestType, bRequest, wValue, wIndex, wLength = struct.unpack("<BBHHH", request)
if stage == 1: # SETUP
if bmRequestType == USB_DIR_OUT | USB_REQ_TYPE_CLASS | USB_REQ_RECIP_INTERFACE:
# Data coming from host, prepare to receive it.
return memoryview(self.usb_buf)[:wLength]
if bmRequestType == USB_DIR_IN | USB_REQ_TYPE_CLASS | USB_REQ_RECIP_INTERFACE:
# Host requests data, prepare to send it.
buf = memoryview(self.usb_buf)[:wLength]
return self.dfu.handle_tx(bRequest, wValue, buf)
elif stage == 3: # ACK
if bmRequestType & USB_DIR_IN:
# EP0 TX sent.
self.dfu.process()
else:
# EP0 RX ready.
buf = memoryview(self.usb_buf)[:wLength]
self.dfu.handle_rx(bRequest, wValue, buf)
return True
# This class handles the DFU state machine.
class DFU:
# DFU class requests.
DETACH = 0
DNLOAD = 1
UPLOAD = 2
GETSTATUS = 3
CLRSTATUS = 4
GETSTATE = 5
ABORT = 6
# DFU states.
STATE_IDLE = 2
STATE_BUSY = 4
STATE_DNLOAD_IDLE = 5
STATE_MANIFEST = 7
STATE_UPLOAD_IDLE = 9
STATE_ERROR = 0xA
# DFU commands.
CMD_NONE = 0
CMD_EXIT = 1
CMD_UPLOAD = 7
CMD_DNLOAD = 8
# Download sub-commands.
CMD_DNLOAD_SET_ADDRESS = 0x21
CMD_DNLOAD_ERASE = 0x41
CMD_DNLOAD_READ_UNPROTECT = 0x92
# Error status flags.
STATUS_OK = 0x00
def __init__(self):
self.state = DFU.STATE_IDLE
self.cmd = DFU.CMD_NONE
self.status = DFU.STATUS_OK
self.error = 0
self.leave_dfu = False
self.addr = 0
self.dnload_block_num = 0
self.dnload_len = 0
self.dnload_buf = bytearray(wTransferSize)
def handle_rx(self, cmd, arg, buf):
# Handle an incoming packet of data.
if cmd == DFU.CLRSTATUS:
self.state = DFU.STATE_IDLE
self.cmd = DFU.CMD_NONE
self.status = DFU.STATUS_OK
self.error = 0
elif cmd == DFU.ABORT:
self.state = DFU.STATE_IDLE
self.cmd = DFU.CMD_NONE
self.status = DFU.STATUS_OK
self.error = 0
elif cmd == DFU.DNLOAD:
if len(buf) == 0:
# Exit DFU.
self.cmd = DFU.CMD_EXIT
else:
# Download data to device.
self.cmd = DFU.CMD_DNLOAD
self.dnload_block_num = arg
self.dnload_len = len(buf)
self.dnload_buf[: len(buf)] = buf
def handle_tx(self, cmd, arg, buf):
# Prepare data to go to the host.
if cmd == DFU.UPLOAD:
if arg >= 2:
self.cmd = DFU.CMD_UPLOAD
addr = (arg - 2) * len(buf) + self.addr
self.do_read(addr, buf)
return buf
return None
elif cmd == DFU.GETSTATUS and len(buf) == 6:
if self.cmd == DFU.CMD_NONE:
pass
elif self.cmd == DFU.CMD_EXIT:
self.state = DFU.STATE_MANIFEST
elif self.cmd == DFU.CMD_UPLOAD:
self.state = DFU.STATE_UPLOAD_IDLE
elif self.cmd == DFU.CMD_DNLOAD:
self.state = DFU.STATE_BUSY
else:
self.state = DFU.STATE_BUSY
# Populate the buffer to return to the host.
buf[0] = self.status
buf[1] = 0
buf[2] = 0
buf[3] = 0
buf[4] = self.state
buf[5] = self.error
# Clear errors now they've been sent to host.
self.status = DFU.STATUS_OK
self.error = 0
return buf
else:
return None
def process(self):
# Transition the DFU state machine.
if self.state == DFU.STATE_MANIFEST:
self.leave_dfu = True
elif self.state == DFU.STATE_BUSY:
if self.cmd == DFU.CMD_DNLOAD:
self.cmd = DFU.CMD_NONE
self.state = self.process_dnload()
def process_dnload(self):
ret = -1 # Assume error.
if self.dnload_block_num == 0:
# Download control commands.
if self.dnload_len >= 1 and self.dnload_buf[0] == DFU.CMD_DNLOAD_ERASE:
if self.dnload_len == 1:
# Mass erase.
ret = self.do_mass_erase()
if ret != 0:
self.cmd = DFU.CMD_NONE
elif self.dnload_len == 5:
# Erase page.
addr = struct.unpack_from("<L", self.dnload_buf, 1)[0]
ret = self.do_page_erase(addr)
elif self.dnload_len >= 1 and self.dnload_buf[0] == DFU.CMD_DNLOAD_SET_ADDRESS:
if self.dnload_len == 5:
# Set address.
self.addr = struct.unpack_from("<L", self.dnload_buf, 1)[0]
ret = 0
elif self.dnload_block_num > 1:
# Write data to memory.
addr = (self.dnload_block_num - 2) * wTransferSize + self.addr
ret = self.do_write(addr, self.dnload_len, self.dnload_buf)
if ret == 0:
return DFU.STATE_DNLOAD_IDLE
else:
return DFU.STATE_ERROR
def do_mass_erase(self):
# This function would implement a mass erase of flash memory.
return 0 # indicate success
def do_page_erase(self, addr):
# This function would implement an erase of a page in flash memory.
return 0 # indicate success
def do_read(self, addr, buf):
# This function would implement a read at the given address of flash memory.
# Return some dummy bytes.
for i in range(len(buf)):
buf[i] = i & 0xFF
return 0 # indicate success
def do_write(self, addr, size, buf):
# This function would implement a write of the given data to flash memory.
return 0 # indicate success
# Create an instance of the DFU state machine.
dfu = DFU()
# Create an instance of the DFU USB handler.
dfu_usb = DFUOverUSB(dfu)
# Switch the USB device to the custom DFU driver.
usbd = machine.USBDevice()
usbd.active(0)
usbd.builtin_driver = usbd.BUILTIN_NONE
usbd.config(
desc_dev=_desc_dev,
desc_cfg=_desc_cfg,
desc_strs=_desc_strs,
control_xfer_cb=dfu_usb._control_xfer_cb,
)
usbd.active(1)
# Wait for the DFU state machine to complete.
while not dfu.leave_dfu:
machine.idle()
# Switch the USB device back to the default built-in driver.
usbd.active(0)
usbd.builtin_driver = usbd.BUILTIN_DEFAULT
usbd.config(
desc_dev=usbd.builtin_driver.desc_dev,
desc_cfg=usbd.builtin_driver.desc_cfg,
desc_strs=(),
)
usbd.active(1)

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