resynch with upstream

This commit is contained in:
Sylvain PILLOT 2024-01-07 20:48:17 +01:00
commit 9cb7ea3693
2926 changed files with 79913 additions and 56051 deletions

View File

@ -1,4 +1,16 @@
#all: Reformat remaining C code that doesn't have a space after a comma.
# all: Update Python formatting to ruff-format.
bbd8760bd9a2302e5abee29db279102bb11d7732
# all: Fix various spelling mistakes found by codespell 2.2.6.
cf490a70917a1b2d38ba9b58e763e0837d0f7ca7
# all: Fix spelling mistakes based on codespell check.
b1229efbd1509654dec6053865ab828d769e29db
# top: Update Python formatting to black "2023 stable style".
8b2748269244304854b3462cb8902952b4dcb892
# all: Reformat remaining C code that doesn't have a space after a comma.
5b700b0af90591d6b1a2c087bb8de6b7f1bfdd2d
# ports: Reformat more C and Python source code.

2
.gitattributes vendored
View File

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

View File

@ -1,6 +1,6 @@
---
name: Security report
about: Report a security issue or vunerability in MicroPython
about: Report a security issue or vulnerability in MicroPython
title: ''
labels: security
assignees: ''

7
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,7 @@
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"

View File

@ -2,15 +2,29 @@ name: Check code formatting
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
code-formatting:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v1
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- name: Install packages
run: source tools/ci.sh && ci_code_formatting_setup
run: source tools/ci.sh && ci_c_code_formatting_setup
- name: Run code formatting
run: source tools/ci.sh && ci_code_formatting_run
run: source tools/ci.sh && ci_c_code_formatting_run
- name: Check code formatting
run: git diff --exit-code
code-spelling:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@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

@ -12,11 +12,15 @@ on:
- 'ports/bare-arm/**'
- 'ports/minimal/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: 100
- name: Install packages
@ -24,4 +28,18 @@ jobs:
- name: Build
run: source tools/ci.sh && ci_code_size_build
- name: Compute code size difference
run: tools/metrics.py diff --error-threshold 0 ~/size0 ~/size1
run: tools/metrics.py diff ~/size0 ~/size1 | tee diff
- name: Save PR number
if: github.event_name == 'pull_request'
env:
PR_NUMBER: ${{ github.event.number }}
run: echo $PR_NUMBER > pr_number
- name: Upload diff
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v4
with:
name: code-size-report
path: |
diff
pr_number
retention-days: 1

105
.github/workflows/code_size_comment.yml vendored Normal file
View File

@ -0,0 +1,105 @@
name: Code size comment
on:
workflow_run:
workflows: [Check code size]
types: [completed]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
comment:
runs-on: ubuntu-20.04
steps:
- name: 'Download artifact'
id: download-artifact
uses: actions/github-script@v7
with:
result-encoding: string
script: |
const fs = require('fs');
const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
});
const matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
return artifact.name == "code-size-report"
});
if (matchArtifact.length === 0) {
console.log('no matching artifact found');
console.log('result: "skip"');
return 'skip';
}
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact[0].id,
archive_format: 'zip',
});
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/code-size-report.zip`, Buffer.from(download.data));
console.log('artifact downloaded to `code-size-report.zip`');
console.log('result: "ok"');
return 'ok';
- name: 'Unzip artifact'
if: steps.download-artifact.outputs.result == 'ok'
run: unzip code-size-report.zip
- name: Post comment to pull request
if: steps.download-artifact.outputs.result == 'ok'
uses: actions/github-script@v7
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
const fs = require('fs');
const prNumber = Number(fs.readFileSync('pr_number'));
const codeSizeReport = `Code size report:
\`\`\`
${fs.readFileSync('diff')}
\`\`\`
`;
const comments = await github.paginate(
github.rest.issues.listComments,
{
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
}
);
comments.reverse();
const previousComment = comments.find(comment =>
comment.user.login === 'github-actions[bot]'
)
// if github-actions[bot] already made a comment, update it,
// otherwise create a new comment.
if (previousComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: previousComment.id,
body: codeSizeReport,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: codeSizeReport,
});
}

View File

@ -2,13 +2,17 @@ name: Check commit message formatting
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: '100'
- uses: actions/setup-python@v1
- uses: actions/setup-python@v5
- name: Check commit message formatting
run: source tools/ci.sh && ci_commit_formatting_run

View File

@ -1,18 +1,23 @@
name: Build docs
on:
push:
pull_request:
paths:
- docs/**
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v1
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- name: Install Python packages
run: pip install Sphinx
run: pip install -r docs/requirements.txt
- name: Build docs
run: make -C docs/ html

View File

@ -10,12 +10,16 @@ on:
- 'py/**'
- 'shared/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
embedding:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Build
run: make -C examples/embedding
run: make -C examples/embedding -f micropython_embed.mk && make -C examples/embedding
- name: Run
run: test "$(./examples/embedding/hello-embed)" = "Hello world of easy embedding!"
run: ./examples/embedding/embed | grep "hello world"

29
.github/workflows/mpremote.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: Package mpremote
on:
push:
pull_request:
paths:
- '.github/workflows/*.yml'
- 'tools/**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# Setting this to zero means fetch all history and tags,
# which hatch-vcs can use to discover the version tag.
fetch-depth: 0
- uses: actions/setup-python@v5
- name: Install build tools
run: pip install build
- name: Build mpremote wheel
run: cd tools/mpremote && python -m build --wheel
- name: Archive mpremote wheel
uses: actions/upload-artifact@v4
with:
name: mpremote
path: |
tools/mpremote/dist/mpremote*.whl

View File

@ -5,13 +5,19 @@ on:
pull_request:
paths:
- '.github/workflows/*.yml'
- 'examples/**'
- 'tests/**'
- 'tools/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04 # use 20.04 to get python2
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_mpy_format_setup
- name: Test mpy-tool.py

View File

@ -8,11 +8,15 @@ on:
- 'tools/**'
- ports/**
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Build ports download metadata
run: mkdir boards && ./tools/autobuild/build-downloads.py . ./boards

View File

@ -8,15 +8,20 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/cc3200/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_cc3200_setup
- name: Build

View File

@ -8,25 +8,50 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/esp32/**'
jobs:
build_idf402:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Install packages
run: source tools/ci.sh && ci_esp32_idf402_setup
- name: Build
run: source tools/ci.sh && ci_esp32_build
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
build_idf44:
jobs:
build_idf:
strategy:
fail-fast: false
matrix:
ci_func: # names are functions in ci.sh
- esp32_build_cmod_spiram_s2
- esp32_build_s3_c3
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Install packages
run: source tools/ci.sh && ci_esp32_idf44_setup
- name: Build
run: source tools/ci.sh && ci_esp32_build
- uses: actions/checkout@v4
- id: idf_ver
name: Read the ESP-IDF version
run: source tools/ci.sh && echo "IDF_VER=$IDF_VER" | tee "$GITHUB_OUTPUT"
- name: Cached ESP-IDF install
id: cache_esp_idf
uses: actions/cache@v3
with:
path: |
./esp-idf/
~/.espressif/
!~/.espressif/dist/
~/.cache/pip/
key: esp-idf-${{ steps.idf_ver.outputs.IDF_VER }}
- name: Install ESP-IDF packages
if: steps.cache_esp_idf.outputs.cache-hit != 'true'
run: source tools/ci.sh && ci_esp32_idf_setup
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: esp32-${{ matrix.ci_func }}
- name: Build ci_${{matrix.ci_func }}
run: source tools/ci.sh && ci_${{ matrix.ci_func }}

View File

@ -8,15 +8,20 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/esp8266/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_esp8266_setup && ci_esp8266_path >> $GITHUB_PATH
- name: Build

View File

@ -8,15 +8,20 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/mimxrt/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_mimxrt_setup
- name: Build

View File

@ -8,15 +8,20 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/nrf/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_nrf_setup
- name: Build

View File

@ -8,15 +8,20 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/powerpc/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_powerpc_setup
- name: Build

View File

@ -8,16 +8,21 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/qemu-arm/**'
- 'tests/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build_and_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_qemu_arm_setup
- name: Build and run test suite

View File

@ -8,15 +8,20 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/renesas-ra/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build_renesas_ra_board:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_renesas_ra_setup
- name: Build

View File

@ -8,15 +8,20 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/rp2/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_rp2_setup
- name: Build

View File

@ -8,15 +8,20 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/samd/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_samd_setup
- name: Build

View File

@ -8,25 +8,28 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/stm32/**'
jobs:
build_pyb:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Install packages
run: source tools/ci.sh && ci_stm32_setup
- name: Build
run: source tools/ci.sh && ci_stm32_pyb_build
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
build_nucleo:
jobs:
build_stm32:
strategy:
fail-fast: false
matrix:
ci_func: # names are functions in ci.sh
- stm32_pyb_build
- stm32_nucleo_build
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_stm32_setup
- name: Build
run: source tools/ci.sh && ci_stm32_nucleo_build
- name: Build ci_${{matrix.ci_func }}
run: source tools/ci.sh && ci_${{ matrix.ci_func }}

View File

@ -1,23 +0,0 @@
name: teensy port
on:
push:
pull_request:
paths:
- '.github/workflows/*.yml'
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'lib/**'
- 'drivers/**'
- 'ports/teensy/**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install packages
run: source tools/ci.sh && ci_teensy_setup
- name: Build
run: source tools/ci.sh && ci_teensy_build

View File

@ -8,16 +8,22 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'examples/**'
- 'mpy-cross/**'
- 'ports/unix/**'
- 'tests/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
minimal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Build
run: source tools/ci.sh && ci_unix_minimal_build
- name: Run main test suite
@ -29,7 +35,7 @@ jobs:
reproducible:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Build with reproducible date
run: source tools/ci.sh && ci_unix_minimal_build
env:
@ -40,7 +46,7 @@ jobs:
standard:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Build
run: source tools/ci.sh && ci_unix_standard_build
- name: Run main test suite
@ -49,10 +55,22 @@ jobs:
if: failure()
run: tests/run-tests.py --print-failures
standard_v2:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: source tools/ci.sh && ci_unix_standard_v2_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_standard_v2_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_unix_coverage_setup
- name: Build
@ -70,7 +88,7 @@ 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@v1
uses: codecov/codecov-action@v3
with:
fail_ci_if_error: true
verbose: true
@ -79,9 +97,9 @@ jobs:
run: tests/run-tests.py --print-failures
coverage_32bit:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04 # use 20.04 to get libffi-dev:i386
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_unix_32bit_setup
- name: Build
@ -97,9 +115,9 @@ jobs:
run: tests/run-tests.py --print-failures
nanbox:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04 # use 20.04 to get python2, and libffi-dev:i386
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_unix_32bit_setup
- name: Build
@ -113,7 +131,7 @@ jobs:
float:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Build
run: source tools/ci.sh && ci_unix_float_build
- name: Run main test suite
@ -125,7 +143,7 @@ jobs:
stackless_clang:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_unix_clang_setup
- name: Build
@ -139,7 +157,7 @@ jobs:
float_clang:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_unix_clang_setup
- name: Build
@ -153,7 +171,7 @@ jobs:
settrace:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Build
run: source tools/ci.sh && ci_unix_settrace_build
- name: Run main test suite
@ -165,7 +183,7 @@ jobs:
settrace_stackless:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Build
run: source tools/ci.sh && ci_unix_settrace_stackless_build
- name: Run main test suite
@ -177,8 +195,8 @@ jobs:
macos:
runs-on: macos-11.0
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.8'
- name: Build
@ -192,7 +210,7 @@ jobs:
qemu_mips:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_unix_qemu_mips_setup
- name: Build
@ -206,7 +224,7 @@ jobs:
qemu_arm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_unix_qemu_arm_setup
- name: Build

View File

@ -8,17 +8,25 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'ports/webassembly/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_webassembly_setup
- name: Build
run: source tools/ci.sh && ci_webassembly_build
- name: Run tests
run: source tools/ci.sh && ci_webassembly_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures

View File

@ -8,15 +8,20 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'ports/unix/**'
- 'ports/windows/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_windows_setup
- name: Build

View File

@ -8,14 +8,19 @@ on:
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'ports/zephyr/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_zephyr_setup
- name: Install Zephyr

11
.github/workflows/ruff.yml vendored Normal file
View File

@ -0,0 +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
- run: pip install --user ruff==0.1.3
- run: ruff check --output-format=github .
- run: ruff format --diff .

21
.gitignore vendored
View File

@ -1,3 +1,4 @@
<<<<<<< HEAD
# Compiled Sources
###################
*.o
@ -23,30 +24,30 @@
# VIM Swap Files
######################
*.swp
=======
# This .gitignore file is intended to be minimal.
#
# If you find that you need additional rules, such as IDE temporary
# files, please do so either via a global .gitignore file (registered
# with core.excludesFile), or by adding private repository-specific
# rules to .git/info/exclude. See https://git-scm.com/docs/gitignore
# for more information.
>>>>>>> upstream/dev
# Build directories
######################
build/
build-*/
docs/genrst/
# Test failure outputs
######################
tests/results/*
# Python cache files
######################
__pycache__/
*.pyc
# Customized Makefile/project overrides
######################
GNUmakefile
user.props
# Generated rst files
######################
genrst/
# MacOS desktop metadata files
######################
.DS_Store

3
.gitmodules vendored
View File

@ -56,3 +56,6 @@
[submodule "lib/micropython-lib"]
path = lib/micropython-lib
url = https://github.com/micropython/micropython-lib.git
[submodule "lib/protobuf-c"]
path = lib/protobuf-c
url = https://github.com/protobuf-c/protobuf-c.git

View File

@ -2,8 +2,8 @@ repos:
- repo: local
hooks:
- id: codeformat
name: MicroPython codeformat.py for changed files
entry: tools/codeformat.py -v -f
name: MicroPython codeformat.py for changed C files
entry: tools/codeformat.py -v -c -f
language: python
- id: verifygitlog
name: MicroPython git commit message format checker
@ -11,3 +11,8 @@ repos:
language: python
verbose: true
stages: [commit-msg]
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.1.3
hooks:
- id: ruff
- id: ruff-format

View File

@ -11,7 +11,7 @@ It's also ok to drop file extensions.
Besides prefix, first line of a commit message should describe a
change clearly and to the point, and be a grammatical sentence with
final full stop. First line should fit within 72 characters. Examples
final full stop. First line must fit within 72 characters. Examples
of good first line of commit messages:
py/objstr: Add splitlines() method.
@ -27,12 +27,9 @@ change beyond 5 lines would likely require such detailed description.
To get good practical examples of good commits and their messages, browse
the `git log` of the project.
When committing you are encouraged to sign-off your commit by adding
"Signed-off-by" lines and similar, eg using "git commit -s". If you don't
explicitly sign-off in this way then the commit message, which includes your
name and email address in the "Author" line, implies your sign-off. In either
case, of explicit or implicit sign-off, you are certifying and signing off
against the following:
When committing you must sign-off your commit by adding "Signed-off-by:"
line(s) at the end of the commit message, e.g. using `git commit -s`. You
are then certifying and signing off against the following:
* That you wrote the change yourself, or took it from a project with
a compatible license (in the latter case the commit message, and possibly
@ -49,32 +46,70 @@ against the following:
* Your contribution including commit message will be publicly and
indefinitely available for anyone to access, including redistribution
under the terms of the project's license.
* Your signature for all of the above, which is the "Signed-off-by" line
or the "Author" line in the commit message, includes your full real name and
a valid and active email address by which you can be contacted in the
foreseeable future.
* Your signature for all of the above, which is the "Signed-off-by" line,
includes your full real name and a valid and active email address by
which you can be contacted in the foreseeable future.
Code auto-formatting
====================
Both C and Python code are auto-formatted using the `tools/codeformat.py`
script. This uses [uncrustify](https://github.com/uncrustify/uncrustify) to
format C code and [black](https://github.com/psf/black) to format Python code.
After making changes, and before committing, run this tool to reformat your
changes to the correct style. Without arguments this tool will reformat all
source code (and may take some time to run). Otherwise pass as arguments to
the tool the files that changed and it will only reformat those.
Both C and Python code formatting are controlled for consistency across the
MicroPython codebase. C code is formatted using the `tools/codeformat.py`
script which uses [uncrustify](https://github.com/uncrustify/uncrustify).
Python code is linted and formatted using
[ruff & ruff format](https://github.com/astral-sh/ruff).
After making changes, and before committing, run `tools/codeformat.py` to
reformat your C code and `ruff format` for any Python code. Without
arguments this tool will reformat all source code (and may take some time
to run). Otherwise pass as arguments to the tool the files that changed,
and it will only reformat those.
**Important**: Use only [uncrustify](https://github.com/uncrustify/uncrustify)
v0.71 or v0.72 for MicroPython. Different uncrustify versions produce slightly
different formatting, and the configuration file formats are often incompatible.
uncrustify
==========
Only [uncrustify](https://github.com/uncrustify/uncrustify) v0.71 or v0.72 can
be used for MicroPython. Different uncrustify versions produce slightly
different formatting, and the configuration file formats are often
incompatible. v0.73 or newer *will not work*.
Depending on your operating system version, it may be possible to install a pre-compiled
uncrustify version:
Ubuntu, Debian
--------------
Ubuntu versions 21.10 or 22.04LTS, and Debian versions bullseye or bookworm all
include v0.72 so can be installed directly:
```
$ apt install uncrustify
```
Arch Linux
----------
The current Arch uncrustify version is too new. There is an [old Arch package
for v0.72](https://archive.archlinux.org/packages/u/uncrustify/) that can be
installed from the Arch Linux archive ([more
information](https://wiki.archlinux.org/title/Downgrading_packages#Arch_Linux_Archive)). Use
the [IgnorePkg feature](https://wiki.archlinux.org/title/Pacman#Skip_package_from_being_upgraded)
to prevent it re-updating.
Brew
----
This command may work, please raise a new Issue if it doesn't:
```
curl -L https://github.com/Homebrew/homebrew-core/raw/2b07d8192623365078a8b855a164ebcdf81494a6/Formula/uncrustify.rb > uncrustify.rb && brew install uncrustify.rb && rm uncrustify.rb
```
Automatic Pre-Commit Hooks
==========================
To have code formatting and commit message conventions automatically checked,
a configuration file is provided for the [pre-commit]
(https://pre-commit.com/) tool.
a configuration file is provided for the [pre-commit](https://pre-commit.com/)
tool.
First install `pre-commit`, either from your system package manager or via
`pip`. When installing `pre-commit` via pip, it is recommended to use a
@ -82,13 +117,17 @@ virtual environment. Other sources, such as Brew are also available, see
[the docs](https://pre-commit.com/index.html#install) for details.
```
$ apt install pre-commit # Ubuntu
$ apt install pre-commit # Ubuntu, Debian
$ pacman -Sy python-precommit # Arch Linux
$ brew install pre-commit # Brew
$ pip install pre-commit # PyPI
```
Then inside the MicroPython repository, register the git hooks for pre-commit
Next, install [uncrustify (see above)](#uncrustify). Other dependencies are managed by
pre-commit automatically, but uncrustify needs to be installed and available on
the PATH.
Then, inside the MicroPython repository, register the git hooks for pre-commit
by running:
```
@ -115,13 +154,22 @@ Tips:
* To ignore the pre-commit message format check temporarily, start the commit
message subject line with "WIP" (for "Work In Progress").
Running pre-commit manually
===========================
Once pre-commit is installed as per the previous section it can be manually
run against the MicroPython python codebase to update file formatting on
demand, with either:
* `pre-commit run --all-files` to fix all files in the MicroPython codebase
* `pre-commit run --file ./path/to/my/file` to fix just one file
* `pre-commit run --file ./path/to/my/folder/*` to fix just one folder
Python code conventions
=======================
Python code follows [PEP 8](https://legacy.python.org/dev/peps/pep-0008/) and
is auto-formatted using [black](https://github.com/psf/black) with a line-length
of 99 characters.
is auto-formatted using [ruff format](https://docs.astral.sh/ruff/formatter)
with a line-length of 99 characters.
Naming conventions:
- Module names are short and all lowercase; eg pyb, stm.
@ -216,7 +264,7 @@ Documentation conventions
=========================
MicroPython generally follows CPython in documentation process and
conventions. reStructuredText syntax is used for the documention.
conventions. reStructuredText syntax is used for the documentation.
Specific conventions/suggestions:

10
LICENSE
View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2013-2022 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
@ -36,7 +36,6 @@ used during the build process and is not part of the compiled source code.
/ (MIT)
/drivers
/cc3100 (BSD-3-clause)
/wiznet5k (BSD-3-clause)
/lib
/asf4 (Apache-2.0)
/axtls (BSD-3-clause)
@ -61,12 +60,17 @@ used during the build process and is not part of the compiled source code.
/tinytest (BSD-3-clause)
/tinyusb (MIT)
/uzlib (Zlib)
/wiznet5k (MIT)
/logo (uses OFL-1.1)
/ports
/cc3200
/hal (BSD-3-clause)
/simplelink (BSD-3-clause)
/FreeRTOS (GPL-2.0 with FreeRTOS exception)
/esp32
/ppp_set_auth.* (Apache-2.0)
/rp2
/mutex_extra.c (BSD-3-clause)
/stm32
/usbd*.c (MCD-ST Liberty SW License Agreement V2)
/stm32_it.* (MIT + BSD-3-clause)
@ -76,8 +80,6 @@ used during the build process and is not part of the compiled source code.
/*/stm32*.h (BSD-3-clause)
/usbdev (MCD-ST Liberty SW License Agreement V2)
/usbhost (MCD-ST Liberty SW License Agreement V2)
/teensy
/core (PJRC.COM)
/zephyr
/src (Apache-2.0)
/tools

View File

@ -1,4 +1,4 @@
[![CI badge](https://github.com/micropython/micropython/workflows/unix%20port/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![codecov](https://codecov.io/gh/micropython/micropython/branch/master/graph/badge.svg?token=I92PfD05sD)](https://codecov.io/gh/micropython/micropython)
[![Unix CI badge](https://github.com/micropython/micropython/actions/workflows/ports_unix.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![STM32 CI badge](https://github.com/micropython/micropython/actions/workflows/ports_stm32.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![Docs CI badge](https://github.com/micropython/micropython/actions/workflows/docs.yml/badge.svg)](https://docs.micropython.org/) [![codecov](https://codecov.io/gh/micropython/micropython/branch/master/graph/badge.svg?token=I92PfD05sD)](https://codecov.io/gh/micropython/micropython)
The MicroPython project
=======================
@ -119,7 +119,6 @@ In addition, the following ports are provided in this repository:
- [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W).
- [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51.
- [stm32](ports/stm32) -- STMicroelectronics STM32 family (including F0, F4, F7, G0, G4, H7, L0, L4, WB)
- [teensy](ports/teensy) -- Teensy 3.x.
- [webassembly](ports/webassembly) -- Emscripten port targeting browsers and NodeJS.
- [zephyr](ports/zephyr) -- Zephyr RTOS.

View File

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

View File

@ -53,7 +53,7 @@ A MicroPython user C module is a directory with the following files:
``SRC_USERMOD_C`` or ``SRC_USERMOD_LIB_C`` variables. The former will be
processed for ``MP_QSTR_`` and ``MP_REGISTER_MODULE`` definitions, the latter
will not (e.g. helpers and library code that isn't MicroPython-specific).
These paths should include your expaned copy of ``$(USERMOD_DIR)``, e.g.::
These paths should include your expanded copy of ``$(USERMOD_DIR)``, e.g.::
SRC_USERMOD_C += $(EXAMPLE_MOD_DIR)/modexample.c
SRC_USERMOD_LIB_C += $(EXAMPLE_MOD_DIR)/utils/algorithm.c
@ -95,9 +95,12 @@ A MicroPython user C module is a directory with the following files:
Basic example
-------------
This simple module named ``cexample`` provides a single function
``cexample.add_ints(a, b)`` which adds the two integer args together and returns
the result. It can be found in the MicroPython source tree
The ``cexample`` module provides examples for a function and a class. The
``cexample.add_ints(a, b)`` function adds two integer args together and returns
the result. The ``cexample.Timer()`` type creates timers that can be used to
measure the elapsed time since the object is instantiated.
The module can be found in the MicroPython source tree
`in the examples directory <https://github.com/micropython/micropython/tree/master/examples/usercmodule/cexample>`_
and has a source file and a Makefile fragment with content as described above::
@ -272,3 +275,13 @@ can now be accessed in Python just like any other builtin module, e.g.
import cexample
print(cexample.add_ints(1, 3))
# should display 4
.. code-block:: python
from cexample import Timer
from time import sleep_ms
watch = Timer()
sleep_ms(1000)
print(watch.time())
# should display approximately 1000

View File

@ -147,10 +147,17 @@ The most relevant method you should know about is this:
.. code-block:: c
mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl) {
// Create a context for this module, and set its globals dict.
mp_module_context_t *context = m_new_obj(mp_module_context_t);
context->module.globals = mp_globals_get();
// Compile the input parse_tree to a raw-code structure.
mp_raw_code_t *rc = mp_compile_to_raw_code(parse_tree, source_file, is_repl);
mp_compiled_module_t cm;
cm.context = context;
mp_compile_to_raw_code(parse_tree, source_file, is_repl, &cm);
// Create and return a function object that executes the outer module.
return mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_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.

View File

@ -100,7 +100,7 @@ For the stm32 port, the ARM cross-compiler is required:
.. code-block:: bash
$ sudo apt-get install arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib
$ sudo apt-get install gcc-arm-none-eabi libnewlib-arm-none-eabi
See the `ARM GCC
toolchain <https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads>`_
@ -228,7 +228,7 @@ You can also specify which board to use:
.. code-block:: bash
$ cd ports/stm32
$ make submodules
$ make BOARD=<board> submodules
$ make BOARD=<board>
See `ports/stm32/boards <https://github.com/micropython/micropython/tree/master/ports/stm32/boards>`_
@ -245,7 +245,7 @@ that you use a virtual environment:
$ python3 -m venv env
$ source env/bin/activate
$ pip install sphinx
$ pip install -r docs/requirements.txt
Navigate to the ``docs`` directory:

View File

@ -38,6 +38,7 @@ The basic MicroPython firmware is implemented in the main port file, e.g ``main.
.. code-block:: c
#include "py/builtin.h"
#include "py/compile.h"
#include "py/gc.h"
#include "py/mperrno.h"
@ -110,6 +111,9 @@ We also need a Makefile at this point for the port:
shared/runtime/pyexec.c \
shared/runtime/stdout_helpers.c \
# Define source files containung qstrs.
SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c
# Define the required object files.
OBJ = $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
@ -147,9 +151,6 @@ The following is an example of an ``mpconfigport.h`` file:
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
// Enable u-modules to be imported with their standard name, like sys.
#define MICROPY_MODULE_WEAK_LINKS (1)
// Fine control over Python builtins, classes, modules, etc.
#define MICROPY_PY_ASYNC_AWAIT (0)
#define MICROPY_PY_BUILTINS_SET (0)

View File

@ -13,6 +13,7 @@ above. The sections below describe the current status of these features.
../differences/python_37.rst
../differences/python_38.rst
../differences/python_39.rst
../differences/python_310.rst
For the features of Python that are implemented by MicroPython, there are
sometimes differences in their behaviour compared to standard Python. The

View File

@ -0,0 +1,238 @@
.. _python_310:
Python 3.10
===========
Python 3.10.0 (final) was released on the 4 October 2021. The Features for 3.10 are
defined in `PEP 619 <https://www.python.org/dev/peps/pep-0619/#features-for-3-10>`_
and a detailed description of the changes can be found in
`What's New in Python 3.10 <https://docs.python.org/3/whatsnew/3.10.html>`_.
.. table::
:widths: 20 60 20
+--------------------------------------------------------+----------------------------------------------------+--------------+
| **New syntax features** | **Status** |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 634 <https://www.python.org/dev/peps/pep-0634/>`_ | Structural Pattern Matching: Specification | [#spm]_ |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 635 <https://www.python.org/dev/peps/pep-0635/>`_ | Structural Pattern Matching: Motivation and | [#spm]_ |
| | Rationale | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 636 <https://www.python.org/dev/peps/pep-0636/>`_ | Structural Pattern Matching: Tutorial | [#spm]_ |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `bpo-12782 | Parenthesized context managers are now officially | |
| <https://github.com/python/cpython/issues/56991>`_ | allowed | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| **New features in the standard library** |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 618 <https://www.python.org/dev/peps/pep-0618/>`_ | Add Optional Length-Checking To zip | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| **Interpreter improvements** |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 626 <https://www.python.org/dev/peps/pep-0626/>`_ | Precise line numbers for debugging and other tools | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| **New typing features** |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 604 <https://www.python.org/dev/peps/pep-0604/>`_ | Allow writing union types as X | Y | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 613 <https://www.python.org/dev/peps/pep-0613/>`_ | Explicit Type Aliases | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 612 <https://www.python.org/dev/peps/pep-0612/>`_ | Parameter Specification Variables | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| **Important deprecations, removals or restrictions** |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 644 <https://www.python.org/dev/peps/pep-0644/>`_ | Require OpenSSL 1.1.1 or newer | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 632 <https://www.python.org/dev/peps/pep-0632/>`_ | Deprecate distutils module. | Not relevant |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 623 <https://www.python.org/dev/peps/pep-0623/>`_ | Deprecate and prepare for the removal of the wstr | Not relevant |
| | member in PyUnicodeObject. | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 624 <https://www.python.org/dev/peps/pep-0624/>`_ | Remove Py_UNICODE encoder APIs | Not relevant |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 597 <https://www.python.org/dev/peps/pep-0597/>`_ | Add optional EncodingWarning | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
Other Language Changes:
.. table::
:widths: 90 10
+-------------------------------------------------------------------------------------------------------------+---------------+
| The :class:`int` type has a new method :meth:`int.bit_count`, returning the | |
| number of ones in the binary expansion of a given integer, also known | |
| as the population count. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| The views returned by :meth:`dict.keys`, :meth:`dict.values` and | |
| :meth:`dict.items` now all have a ``mapping`` attribute that gives a | |
| :class:`types.MappingProxyType` object wrapping the original | |
| dictionary. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| :pep:`618`: The :func:`zip` function now has an optional ``strict`` flag, used | |
| to require that all the iterables have an equal length. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Builtin and extension functions that take integer arguments no longer accept | |
| :class:`~decimal.Decimal`\ s, :class:`~fractions.Fraction`\ s and other | |
| objects that can be converted to integers only with a loss (e.g. that have | |
| the :meth:`~object.__int__` method but do not have the | |
| :meth:`~object.__index__` method). | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| If :func:`object.__ipow__` returns :const:`NotImplemented`, the operator will | |
| correctly fall back to :func:`object.__pow__` and :func:`object.__rpow__` as expected. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Assignment expressions can now be used unparenthesized within set literals | |
| and set comprehensions, as well as in sequence indexes (but not slices). | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Functions have a new ``__builtins__`` attribute which is used to look for | |
| builtin symbols when a function is executed, instead of looking into | |
| ``__globals__['__builtins__']``. The attribute is initialized from | |
| ``__globals__["__builtins__"]`` if it exists, else from the current builtins. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Two new builtin functions -- :func:`aiter` and :func:`anext` have been added | |
| to provide asynchronous counterparts to :func:`iter` and :func:`next`, | |
| respectively. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Static methods (:func:`@staticmethod <staticmethod>`) and class methods | |
| (:func:`@classmethod <classmethod>`) now inherit the method attributes | |
| (``__module__``, ``__name__``, ``__qualname__``, ``__doc__``, | |
| ``__annotations__``) and have a new ``__wrapped__`` attribute. | |
| Moreover, static methods are now callable as regular functions. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Annotations for complex targets (everything beside ``simple name`` targets | |
| defined by :pep:`526`) no longer cause any runtime effects with ``from __future__ import annotations``. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Class and module objects now lazy-create empty annotations dicts on demand. | |
| The annotations dicts are stored in the objects ``__dict__`` for | |
| backwards compatibility. This improves the best practices for working | |
| with ``__annotations__``. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Annotations consist of ``yield``, ``yield from``, ``await`` or named expressions | |
| are now forbidden under ``from __future__ import annotations`` due to their side | |
| effects. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Usage of unbound variables, ``super()`` and other expressions that might | |
| alter the processing of symbol table as annotations are now rendered | |
| effectless under ``from __future__ import annotations``. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Hashes of NaN values of both :class:`float` type and | |
| :class:`decimal.Decimal` type now depend on object identity. Formerly, they | |
| always hashed to ``0`` even though NaN values are not equal to one another. | |
| This caused potentially quadratic runtime behavior due to excessive hash | |
| collisions when creating dictionaries and sets containing multiple NaNs. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| A :exc:`SyntaxError` (instead of a :exc:`NameError`) will be raised when deleting | |
| the :const:`__debug__` constant. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| :exc:`SyntaxError` exceptions now have ``end_lineno`` and | |
| ``end_offset`` attributes. They will be ``None`` if not determined. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
Changes to built-in modules:
.. table::
:widths: 90 10
+---------------------------------------------------------------------------------------------------------------+---------------+
| `asyncio <https://docs.python.org/3/whatsnew/3.10.html#asyncio>`_ |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Add missing :meth:`~asyncio.events.AbstractEventLoop.connect_accepted_socket` | |
| method. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| `array <https://docs.python.org/3/whatsnew/3.10.html#array>`_ |
+---------------------------------------------------------------------------------------------------------------+---------------+
| The :meth:`~array.array.index` method of :class:`array.array` now has | |
| optional *start* and *stop* parameters. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| `gc <https://docs.python.org/3/whatsnew/3.10.html#gc>`_ |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Add audit hooks for :func:`gc.get_objects`, :func:`gc.get_referrers` and | |
| :func:`gc.get_referents`. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| `hashlib <https://docs.python.org/3/whatsnew/3.10.html#hashlib>`_ |
+---------------------------------------------------------------------------------------------------------------+---------------+
| The hashlib module requires OpenSSL 1.1.1 or newer. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| The hashlib module has preliminary support for OpenSSL 3.0.0. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| The pure-Python fallback of :func:`~hashlib.pbkdf2_hmac` is deprecated. In | |
| the future PBKDF2-HMAC will only be available when Python has been built with | |
| OpenSSL support. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| `os <https://docs.python.org/3/whatsnew/3.10.html#os>`_ |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Add :func:`os.cpu_count()` support for VxWorks RTOS. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Add a new function :func:`os.eventfd` and related helpers to wrap the | |
| ``eventfd2`` syscall on Linux. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Add :func:`os.splice()` that allows to move data between two file | |
| descriptors without copying between kernel address space and user | |
| address space, where one of the file descriptors must refer to a | |
| pipe. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Add :data:`~os.O_EVTONLY`, :data:`~os.O_FSYNC`, :data:`~os.O_SYMLINK` | |
| and :data:`~os.O_NOFOLLOW_ANY` for macOS. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| `platform <https://docs.python.org/3/whatsnew/3.10.html#platform>`_ |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Add :func:`platform.freedesktop_os_release()` to retrieve operation system | |
| identification from `freedesktop.org os-release | |
| <https://www.freedesktop.org/software/systemd/man/os-release.html>`_ standard file. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| `socket <https://docs.python.org/3/whatsnew/3.10.html#socket>`_ |
+---------------------------------------------------------------------------------------------------------------+---------------+
| The exception :exc:`socket.timeout` is now an alias of :exc:`TimeoutError`. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Add option to create MPTCP sockets with ``IPPROTO_MPTCP``. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Add ``IP_RECVTOS`` option to receive the type of service (ToS) or DSCP/ECN fields. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| `ssl <https://docs.python.org/3/whatsnew/3.10.html#ssl>`_ |
+---------------------------------------------------------------------------------------------------------------+---------------+
| The ssl module requires OpenSSL 1.1.1 or newer. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| The ssl module has preliminary support for OpenSSL 3.0.0 and new option | |
| :data:`~ssl.OP_IGNORE_UNEXPECTED_EOF`. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Deprecated function and use of deprecated constants now result in | |
| a :exc:`DeprecationWarning`. :attr:`ssl.SSLContext.options` has | |
| :data:`~ssl.OP_NO_SSLv2` and :data:`~ssl.OP_NO_SSLv3` set by default and | |
| therefore cannot warn about setting the flag again. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| The ssl module now has more secure default settings. Ciphers without forward | |
| secrecy or SHA-1 MAC are disabled by default. Security level 2 prohibits | |
| weak RSA, DH, and ECC keys with less than 112 bits of security. | |
| :class:`~ssl.SSLContext` defaults to minimum protocol version TLS 1.2. | |
| Settings are based on Hynek Schlawack's research. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| The deprecated protocols SSL 3.0, TLS 1.0, and TLS 1.1 are no longer | |
| officially supported. Python does not block them actively. However | |
| OpenSSL build options, distro configurations, vendor patches, and cipher | |
| suites may prevent a successful handshake. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Add a *timeout* parameter to the :func:`ssl.get_server_certificate` function. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| The ssl module uses heap-types and multi-phase initialization. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| A new verify flag :data:`~ssl.VERIFY_X509_PARTIAL_CHAIN` has been added. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| `sys <https://docs.python.org/3/whatsnew/3.10.html#sys>`_ |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Add :data:`sys.orig_argv` attribute: the list of the original command line | |
| arguments passed to the Python executable. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Add :data:`sys.stdlib_module_names`, containing the list of the standard library | |
| module names. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| `_thread <https://docs.python.org/3/whatsnew/3.10.html#_thread>`_ |
+---------------------------------------------------------------------------------------------------------------+---------------+
| :func:`_thread.interrupt_main` now takes an optional signal number to | |
| simulate (the default is still :data:`signal.SIGINT`). | |
+---------------------------------------------------------------------------------------------------------------+---------------+
.. rubric:: Notes
.. [#spm] The structural pattern matching feature is discussed in `issue #7847 <https://github.com/micropython/micropython/issues/7847>`_.

View File

@ -11,30 +11,30 @@ and a detailed description of the changes can be found in
.. table::
:widths: 20 60 20
+--------------------------------------------------------+----------------------------------------------------+--------------+
| **Features** | | **Status** |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 573 <https://www.python.org/dev/peps/pep-0573/>`_ | Fast access to module state from methods of C | |
| | extension types | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 584 <https://www.python.org/dev/peps/pep-0584/>`_ | Union operators added to dict | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 585 <https://www.python.org/dev/peps/pep-0584/>`_ | Type hinting generics in standard collections | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 593 <https://www.python.org/dev/peps/pep-0593/>`_ | Flexible function and variable annotations | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 602 <https://www.python.org/dev/peps/pep-0602/>`_ | CPython adopts an annual release cycle. Instead of | |
| | annual, aiming for two month release cycle | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 614 <https://www.python.org/dev/peps/pep-0614/>`_ | Relaxed grammar restrictions on decorators | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 615 <https://www.python.org/dev/peps/pep-0615/>`_ | The IANA Time Zone Database is now present in the | |
| | standard library in the zoneinfo module | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 616 <https://www.python.org/dev/peps/pep-0616/>`_ | String methods to remove prefixes and suffixes | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 617 <https://www.python.org/dev/peps/pep-0617/>`_ | CPython now uses a new parser based on PEG | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
+--------------------------------------------------------+----------------------------------------------------+----------------------+
| **Features** | | **Status** |
+--------------------------------------------------------+----------------------------------------------------+----------------------+
| `PEP 573 <https://www.python.org/dev/peps/pep-0573/>`_ | Fast access to module state from methods of C | Not relevant |
| | extension types | |
+--------------------------------------------------------+----------------------------------------------------+----------------------+
| `PEP 584 <https://www.python.org/dev/peps/pep-0584/>`_ | Union operators added to dict | Complete [#pep584]_ |
+--------------------------------------------------------+----------------------------------------------------+----------------------+
| `PEP 585 <https://www.python.org/dev/peps/pep-0584/>`_ | Type hinting generics in standard collections | |
+--------------------------------------------------------+----------------------------------------------------+----------------------+
| `PEP 593 <https://www.python.org/dev/peps/pep-0593/>`_ | Flexible function and variable annotations | |
+--------------------------------------------------------+----------------------------------------------------+----------------------+
| `PEP 602 <https://www.python.org/dev/peps/pep-0602/>`_ | CPython adopts an annual release cycle. Instead of | Not relevant |
| | annual, aiming for two month release cycle | |
+--------------------------------------------------------+----------------------------------------------------+----------------------+
| `PEP 614 <https://www.python.org/dev/peps/pep-0614/>`_ | Relaxed grammar restrictions on decorators | |
+--------------------------------------------------------+----------------------------------------------------+----------------------+
| `PEP 615 <https://www.python.org/dev/peps/pep-0615/>`_ | The IANA Time Zone Database is now present in the | |
| | standard library in the zoneinfo module | |
+--------------------------------------------------------+----------------------------------------------------+----------------------+
| `PEP 616 <https://www.python.org/dev/peps/pep-0616/>`_ | String methods to remove prefixes and suffixes | |
+--------------------------------------------------------+----------------------------------------------------+----------------------+
| `PEP 617 <https://www.python.org/dev/peps/pep-0617/>`_ | CPython now uses a new parser based on PEG | Not relevant |
+--------------------------------------------------------+----------------------------------------------------+----------------------+
Other Language Changes:
@ -128,3 +128,7 @@ Changes to built-in modules:
| Previously, *sys.stderr* was block-buffered when non-interactive. Now stderr defaults to always being | |
| line-buffered | |
+---------------------------------------------------------------------------------------------------------------+---------------+
.. rubric:: Notes
.. [#pep584] PEP 584 ``dict`` union operator is only available on MicroPython builds with ``MICROPY_CPYTHON_COMPAT`` enabled.

View File

@ -57,7 +57,6 @@ The :mod:`esp32` module::
import esp32
esp32.hall_sensor() # read the internal hall sensor
esp32.raw_temperature() # read the internal temperature of the MCU, in Fahrenheit
esp32.ULP() # access to the Ultra-Low-Power Co-processor
@ -68,6 +67,9 @@ by reading the temperature sensor immediately after waking up from sleep.
Networking
----------
WLAN
^^^^
The :mod:`network` module::
import network
@ -99,7 +101,7 @@ A useful function for connecting to your local WiFi network is::
print('network config:', wlan.ifconfig())
Once the network is established the :mod:`socket <socket>` module can be used
to create and use TCP/UDP sockets as usual, and the ``urequests`` module for
to create and use TCP/UDP sockets as usual, and the ``requests`` module for
convenient HTTP requests.
After a call to ``wlan.connect()``, the device will by default retry to connect
@ -110,6 +112,55 @@ calling ``wlan.config(reconnects=n)``, where n are the number of desired reconne
attempts (0 means it won't retry, -1 will restore the default behaviour of trying
to reconnect forever).
LAN
^^^
To use the wired interfaces one has to specify the pins and mode ::
import network
lan = network.LAN(mdc=PIN_MDC, ...) # Set the pin and mode configuration
lan.active(True) # activate the interface
lan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses
The keyword arguments for the constructor defining the PHY type and interface are:
- mdc=pin-object # set the mdc and mdio pins.
- mdio=pin-object
- power=pin-object # set the pin which switches the power of the PHY device.
- phy_type=<type> # Select the PHY device type. Supported devices are PHY_LAN8710,
PHY_LAN8720, PH_IP101, PHY_RTL8201, PHY_DP83848 and PHY_KSZ8041
- phy_addr=number # The address number of the PHY device.
- ref_clk_mode=mode # Defines, whether the ref_clk at the ESP32 is an input
or output. Suitable values are Pin.IN and Pin.OUT.
- ref_clk=pin-object # defines the Pin used for ref_clk.
These are working configurations for LAN interfaces of popular boards::
# Olimex ESP32-GATEWAY: power controlled by Pin(5)
# Olimex ESP32 PoE and ESP32-PoE ISO: power controlled by Pin(12)
lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), power=machine.Pin(5),
phy_type=network.PHY_LAN8720, phy_addr=0,
ref_clk=machine.Pin(17), ref_clk_mode=machine.Pin.OUT)
# Wireless-Tag's WT32-ETH01
lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18),
phy_type=network.PHY_LAN8720, phy_addr=1, power=None)
# Wireless-Tag's WT32-ETH01 v1.4
lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18),
phy_type=network.PHY_LAN8720, phy_addr=1,
power=machine.Pin(16))
# Espressif ESP32-Ethernet-Kit_A_V1.2
lan = network.LAN(id=0, mdc=Pin(23), mdio=Pin(18), power=Pin(5),
phy_type=network.PHY_IP101, phy_addr=1)
Delay and timing
----------------
@ -241,8 +292,8 @@ Use the :ref:`machine.PWM <machine.PWM>` class::
from machine import Pin, PWM
pwm0 = PWM(Pin(0)) # create PWM object from a pin
freq = pwm0.freq() # get current frequency (default 5kHz)
pwm0 = PWM(Pin(0), freq=5000, duty_u16=32768) # create PWM object from a pin
freq = pwm0.freq() # get current frequency
pwm0.freq(1000) # set PWM frequency from 1Hz to 40MHz
duty = pwm0.duty() # get current duty cycle, range 0-1023 (default 512, 50%)
@ -279,6 +330,19 @@ possible at the same frequency.
See more examples in the :ref:`esp32_pwm` tutorial.
DAC (digital to analog conversion)
----------------------------------
On the ESP32, DAC functionality is available on pins 25, 26.
On the ESP32S2, DAC functionality is available on pins 17, 18.
Use the DAC::
from machine import DAC, Pin
dac = DAC(Pin(25)) # create an DAC object acting on a pin
dac.write(128) # set a raw analog value in the range 0-255, 50% now
ADC (analog to digital conversion)
----------------------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

View File

@ -17,7 +17,7 @@ Requirements
The first thing you need is a board with an ESP32 chip. The MicroPython
software supports the ESP32 chip itself and any board should work. The main
characteristic of a board is how the GPIO pins are connected to the outside
world, and whether it includes a built-in USB-serial convertor to make the
world, and whether it includes a built-in USB-serial converter to make the
UART available to your PC.
Names of pins will be given in this tutorial using the chip names (eg GPIO2)
@ -59,7 +59,7 @@ bootloader mode, and second you need to copy across the firmware. The exact
procedure for these steps is highly dependent on the particular board and you will
need to refer to its documentation for details.
Fortunately, most boards have a USB connector, a USB-serial convertor, and the DTR
Fortunately, most boards have a USB connector, a USB-serial converter, and the DTR
and RTS pins wired in a special way then deploying the firmware should be easy as
all steps can be done automatically. Boards that have such features
include the Adafruit Feather HUZZAH32, M5Stack, Wemos LOLIN32, and TinyPICO
@ -104,7 +104,7 @@ Serial prompt
Once you have the firmware on the device you can access the REPL (Python prompt)
over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial
convertor, depending on your board. The baudrate is 115200.
converter, depending on your board. The baudrate is 115200.
From here you can now follow the ESP8266 tutorial, because these two Espressif chips
are very similar when it comes to using MicroPython on them. The ESP8266 tutorial
@ -124,7 +124,7 @@ after it, here are troubleshooting recommendations:
* The flashing instructions above use flashing speed of 460800 baud, which is
good compromise between speed and stability. However, depending on your
module/board, USB-UART convertor, cables, host OS, etc., the above baud
module/board, USB-UART converter, cables, host OS, etc., the above baud
rate may be too high and lead to errors. Try a more common 115200 baud
rate instead in such cases.

View File

@ -42,3 +42,83 @@ for this:
The MCPWM0 peripheral is in bit position 17 of the above two registers, hence
the value of ``DPORT_PWM0_CLK_EN``.
Synchronous access to pins directly via registers
-------------------------------------------------
The following code shows how to access pins directly via registers. It has been
tested on a generic ESP32 board. It configures pins 16, 17, 32 and 33 in output
mode via registers, and switches pin output values via registers. Pins 16 and
17 are switched simultaneously.
.. code-block:: python3
from micropython import const
from machine import mem32, Pin
GPIO_OUT_REG = const(0x3FF44004) # GPIO 0-31 output register
GPIO_OUT1_REG = const(0x3FF44010) # GPIO 32-39 output register
GPIO_ENABLE_REG = const(0x3FF44020) # GPIO 0-31 output enable register
GPIO_ENABLE1_REG = const(0x3FF4402C) # GPIO 32-39 output enable register
M16 = 1 << 16 # Pin(16) bit mask
M17 = 1 << 17 # Pin(17) bit mask
M32 = 1 << (32-32) # Pin(32) bit mask
M33 = 1 << (33-32) # Pin(33) bit mask
# Enable pin output mode like
# p16 = Pin(16, mode=Pin.OUT)
# p17 = Pin(17, mode=Pin.OUT)
# p32 = Pin(32, mode=Pin.OUT)
# p33 = Pin(33, mode=Pin.OUT)
mem32[GPIO_ENABLE_REG] = mem32[GPIO_ENABLE_REG] | M16 | M17
mem32[GPIO_ENABLE1_REG] = mem32[GPIO_ENABLE1_REG] | M32 | M33
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
# Set outputs to 1 like
# p16(1)
# p17(1)
# p32(1)
# p33(1)
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] | M16 | M17
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] | M32 | M33
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
# Set outputs to 0 like
# p16(0)
# p17(0)
# p32(0)
# p33(0)
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] & ~(M16 | M17)
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] & ~(M32 | M33)
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
while True:
# Set outputs to 1
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] | M16 | M17
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] | M32 | M33
# Set outputs to 0
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] & ~(M16 | M17)
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] & ~(M32 | M33)
Output is::
0x0 0x0
0x30000 0x3
0x0 0x0
Pins 16 and 17 are switched synchronously:
.. image:: img/mem32_gpio_output.jpg
Same image on pins 32 and 33.
Note that pins 34-36 and 39 are inputs only. Also pins 1 and 3 are Tx, Rx of the REPL UART,
pins 6-11 are connected to the built-in SPI flash.

View File

@ -50,7 +50,7 @@ low all of the time.
* Example of a smooth frequency change::
from utime import sleep
from time import sleep
from machine import Pin, PWM
F_MIN = 500
@ -75,7 +75,7 @@ low all of the time.
* Example of a smooth duty change::
from utime import sleep
from time import sleep
from machine import Pin, PWM
DUTY_MAX = 2**16 - 1

View File

@ -18,7 +18,7 @@ The first thing you need is a board with an ESP8266 chip. The MicroPython
software supports the ESP8266 chip itself and any board should work. The main
characteristic of a board is how much flash it has, how the GPIO pins are
connected to the outside world, and whether it includes a built-in USB-serial
convertor to make the UART available to your PC.
converter to make the UART available to your PC.
The minimum requirement for flash size is 1Mbyte. There is also a special
build for boards with 512KB, but it is highly limited comparing to the
@ -70,7 +70,7 @@ need to put your device in boot-loader mode, and second you need to copy across
the firmware. The exact procedure for these steps is highly dependent on the
particular board and you will need to refer to its documentation for details.
If you have a board that has a USB connector, a USB-serial convertor, and has
If you have a board that has a USB connector, a USB-serial converter, and has
the DTR and RTS pins wired in a special way then deploying the firmware should
be easy as all steps can be done automatically. Boards that have such features
include the Adafruit Feather HUZZAH and NodeMCU boards.
@ -128,7 +128,7 @@ Serial prompt
Once you have the firmware on the device you can access the REPL (Python prompt)
over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial
convertor, depending on your board. The baudrate is 115200. The next part of
converter, depending on your board. The baudrate is 115200. The next part of
the tutorial will discuss the prompt in more detail.
WiFi
@ -137,7 +137,7 @@ WiFi
After a fresh install and boot the device configures itself as a WiFi access
point (AP) that you can connect to. The ESSID is of the form MicroPython-xxxxxx
where the x's are replaced with part of the MAC address of your device (so will
be the same everytime, and most likely different for all ESP8266 chips). The
be the same every time, and most likely different for all ESP8266 chips). The
password for the WiFi is micropythoN (note the upper-case N). Its IP address
will be 192.168.4.1 once you connect to its network. WiFi configuration will
be discussed in more detail later in the tutorial.
@ -169,7 +169,7 @@ after it, here are troubleshooting recommendations:
* The flashing instructions above use flashing speed of 460800 baud, which is
good compromise between speed and stability. However, depending on your
module/board, USB-UART convertor, cables, host OS, etc., the above baud
module/board, USB-UART converter, cables, host OS, etc., the above baud
rate may be too high and lead to errors. Try a more common 115200 baud
rate instead in such cases.

View File

@ -13,7 +13,7 @@ REPL over the serial port
The REPL is always available on the UART0 serial peripheral, which is connected
to the pins GPIO1 for TX and GPIO3 for RX. The baudrate of the REPL is 115200.
If your board has a USB-serial convertor on it then you should be able to access
If your board has a USB-serial converter on it then you should be able to access
the REPL directly from your PC. Otherwise you will need to have a way of
communicating with the UART.

View File

@ -17,3 +17,4 @@ MicroPython documentation and references
unix/quickref.rst
zephyr/quickref.rst
renesas-ra/quickref.rst
samd/quickref.rst

View File

@ -27,3 +27,55 @@ Classes
Append new elements as contained in *iterable* to the end of
array, growing it.
.. method:: __getitem__(index)
Indexed read of the array, called as ``a[index]`` (where ``a`` is an ``array``).
Returns a value if *index* is an ``int`` and an ``array`` if *index* is a slice.
Negative indices count from the end and ``IndexError`` is thrown if the index is
out of range.
**Note:** ``__getitem__`` cannot be called directly (``a.__getitem__(index)`` fails) and
is not present in ``__dict__``, however ``a[index]`` does work.
.. method:: __setitem__(index, value)
Indexed write into the array, called as ``a[index] = value`` (where ``a`` is an ``array``).
``value`` is a single value if *index* is an ``int`` and an ``array`` if *index* is a slice.
Negative indices count from the end and ``IndexError`` is thrown if the index is out of range.
**Note:** ``__setitem__`` cannot be called directly (``a.__setitem__(index, value)`` fails) and
is not present in ``__dict__``, however ``a[index] = value`` does work.
.. method:: __len__()
Returns the number of items in the array, called as ``len(a)`` (where ``a`` is an ``array``).
**Note:** ``__len__`` cannot be called directly (``a.__len__()`` fails) and the
method is not present in ``__dict__``, however ``len(a)`` does work.
.. method:: __add__(other)
Return a new ``array`` that is the concatenation of the array with *other*, called as
``a + other`` (where ``a`` and *other* are both ``arrays``).
**Note:** ``__add__`` cannot be called directly (``a.__add__(other)`` fails) and
is not present in ``__dict__``, however ``a + other`` does work.
.. method:: __iadd__(other)
Concatenates the array with *other* in-place, called as ``a += other`` (where ``a`` and *other*
are both ``arrays``). Equivalent to ``extend(other)``.
**Note:** ``__iadd__`` cannot be called directly (``a.__iadd__(other)`` fails) and
is not present in ``__dict__``, however ``a += other`` does work.
.. method:: __repr__()
Returns the string representation of the array, called as ``str(a)`` or ``repr(a)```
(where ``a`` is an ``array``). Returns the string ``"array(<type>, [<elements>])"``,
where ``<type>`` is the type code letter for the array and ``<elements>`` is a comma
separated list of the elements of the array.
**Note:** ``__repr__`` cannot be called directly (``a.__repr__()`` fails) and
is not present in ``__dict__``, however ``str(a)`` and ``repr(a)`` both work.

View File

@ -1,7 +1,7 @@
:mod:`uasyncio` --- asynchronous I/O scheduler
==============================================
:mod:`asyncio` --- asynchronous I/O scheduler
=============================================
.. module:: uasyncio
.. module:: asyncio
:synopsis: asynchronous I/O scheduler for writing concurrent code
|see_cpython_module|
@ -9,27 +9,27 @@
Example::
import uasyncio
import asyncio
async def blink(led, period_ms):
while True:
led.on()
await uasyncio.sleep_ms(5)
await asyncio.sleep_ms(5)
led.off()
await uasyncio.sleep_ms(period_ms)
await asyncio.sleep_ms(period_ms)
async def main(led1, led2):
uasyncio.create_task(blink(led1, 700))
uasyncio.create_task(blink(led2, 400))
await uasyncio.sleep_ms(10_000)
asyncio.create_task(blink(led1, 700))
asyncio.create_task(blink(led2, 400))
await asyncio.sleep_ms(10_000)
# Running on a pyboard
from pyb import LED
uasyncio.run(main(LED(1), LED(2)))
asyncio.run(main(LED(1), LED(2)))
# Running on a generic board
from machine import Pin
uasyncio.run(main(Pin(1), Pin(2)))
asyncio.run(main(Pin(1), Pin(2)))
Core functions
--------------
@ -71,9 +71,9 @@ Additional functions
than *timeout* seconds. If *awaitable* is not a task then a task will be
created from it.
If a timeout occurs, it cancels the task and raises ``uasyncio.TimeoutError``:
If a timeout occurs, it cancels the task and raises ``asyncio.TimeoutError``:
this should be trapped by the caller. The task receives
``uasyncio.CancelledError`` which may be ignored or trapped using ``try...except``
``asyncio.CancelledError`` which may be ignored or trapped using ``try...except``
or ``try...finally`` to run cleanup code.
Returns the return value of *awaitable*.
@ -108,7 +108,7 @@ class Task
.. method:: Task.cancel()
Cancel the task by injecting ``uasyncio.CancelledError`` into it. The task may
Cancel the task by injecting ``asyncio.CancelledError`` into it. The task may
ignore this exception. Cleanup code may be run by trapping it, or via
``try ... finally``.
@ -148,8 +148,9 @@ class ThreadSafeFlag
.. class:: ThreadSafeFlag()
Create a new flag which can be used to synchronise a task with code running
outside the uasyncio loop, such as other threads, IRQs, or scheduler
callbacks. Flags start in the cleared state.
outside the asyncio loop, such as other threads, IRQs, or scheduler
callbacks. Flags start in the cleared state. The class does not currently
work under the Unix build of MicroPython.
.. method:: ThreadSafeFlag.set()
@ -200,10 +201,12 @@ class Lock
TCP stream connections
----------------------
.. function:: open_connection(host, port)
.. function:: open_connection(host, port, ssl=None)
Open a TCP connection to the given *host* and *port*. The *host* address will be
resolved using `socket.getaddrinfo`, which is currently a blocking call.
If *ssl* is a `ssl.SSLContext` object, this context is used to create the transport;
if *ssl* is ``True``, a default context is used.
Returns a pair of streams: a reader and a writer stream.
Will raise a socket-specific ``OSError`` if the host could not be resolved or if
@ -211,12 +214,14 @@ TCP stream connections
This is a coroutine.
.. function:: start_server(callback, host, port, backlog=5)
.. function:: start_server(callback, host, port, backlog=5, ssl=None)
Start a TCP server on the given *host* and *port*. The *callback* will be
called with incoming, accepted connections, and be passed 2 arguments: reader
and writer streams for the connection.
If *ssl* is a `ssl.SSLContext` object, this context is used to create the transport.
Returns a `Server` object.
This is a coroutine.

View File

@ -44,7 +44,7 @@ Configuration
Get or set configuration values of the BLE interface. To get a value the
parameter name should be quoted as a string, and just one parameter is
queried at a time. To set values use the keyword syntax, and one ore more
queried at a time. To set values use the keyword syntax, and one or more
parameter can be set at a time.
Currently supported values are:
@ -183,12 +183,10 @@ Event Handling
conn_handle, value_handle, char_data = data
elif event == _IRQ_GATTC_READ_DONE:
# A gattc_read() has completed.
# Note: The value_handle will be zero on btstack (but present on NimBLE).
# Note: Status will be zero on success, implementation-specific value otherwise.
conn_handle, value_handle, status = data
elif event == _IRQ_GATTC_WRITE_DONE:
# A gattc_write() has completed.
# Note: The value_handle will be zero on btstack (but present on NimBLE).
# Note: Status will be zero on success, implementation-specific value otherwise.
conn_handle, value_handle, status = data
elif event == _IRQ_GATTC_NOTIFY:
@ -514,19 +512,24 @@ writes from a client to a given characteristic, use
Sends a notification request to a connected client.
If *data* is not ``None``, then that value is sent to the client as part of
the notification. The local value will not be modified.
If *data* is ``None`` (the default), then the current local value (as set
with :meth:`gatts_write <BLE.gatts_write>`) will be sent.
Otherwise, if *data* is ``None``, then the current local value (as
set with :meth:`gatts_write <BLE.gatts_write>`) will be sent.
Otherwise, if *data* is not ``None``, then that value is sent to the client
as part of the notification. The local value will not be modified.
**Note:** The notification will be sent regardless of the subscription
status of the client to this characteristic.
.. method:: BLE.gatts_indicate(conn_handle, value_handle, /)
.. method:: BLE.gatts_indicate(conn_handle, value_handle, data=None, /)
Sends an indication request containing the characteristic's current value to
a connected client.
Sends a indication request to a connected client.
If *data* is ``None`` (the default), then the current local value (as set
with :meth:`gatts_write <BLE.gatts_write>`) will be sent.
Otherwise, if *data* is not ``None``, then that value is sent to the client
as part of the indication. The local value will not be modified.
On acknowledgment (or failure, e.g. timeout), the
``_IRQ_GATTS_INDICATE_DONE`` event will be raised.

182
docs/library/deflate.rst Normal file
View File

@ -0,0 +1,182 @@
:mod:`deflate` -- deflate compression & decompression
=====================================================
.. module:: deflate
:synopsis: deflate compression & decompression
This module allows compression and decompression of binary data with the
`DEFLATE algorithm <https://en.wikipedia.org/wiki/DEFLATE>`_
(commonly used in the zlib library and gzip archiver).
**Availability:**
* Added in MicroPython v1.21.
* Decompression: Enabled via the ``MICROPY_PY_DEFLATE`` build option, on by default
on ports with the "extra features" level or higher (which is most boards).
* Compression: Enabled via the ``MICROPY_PY_DEFLATE_COMPRESS`` build option, on
by default on ports with the "full features" level or higher (generally this means
you need to build your own firmware to enable this).
Classes
-------
.. class:: DeflateIO(stream, format=AUTO, wbits=0, close=False, /)
This class can be used to wrap a *stream* which is any
:term:`stream-like <stream>` object such as a file, socket, or stream
(including :class:`io.BytesIO`). It is itself a stream and implements the
standard read/readinto/write/close methods.
The *stream* must be a blocking stream. Non-blocking streams are currently
not supported.
The *format* can be set to any of the constants defined below, and defaults
to ``AUTO`` which for decompressing will auto-detect gzip or zlib streams,
and for compressing it will generate a raw stream.
The *wbits* parameter sets the base-2 logarithm of the DEFLATE dictionary
window size. So for example, setting *wbits* to ``10`` sets the window size
to 1024 bytes. Valid values are ``5`` to ``15`` inclusive (corresponding to
window sizes of 32 to 32k bytes).
If *wbits* is set to ``0`` (the default), then for compression a window size
of 256 bytes will be used (as if *wbits* was set to 8). For decompression, it
depends on the format:
* ``RAW`` will use 256 bytes (corresponding to *wbits* set to 8).
* ``ZLIB`` (or ``AUTO`` with zlib detected) will use the value from the zlib
header.
* ``GZIP`` (or ``AUTO`` with gzip detected) will use 32 kilobytes
(corresponding to *wbits* set to 15).
See the :ref:`window size <deflate_wbits>` notes below for more information
about the window size, zlib, and gzip streams.
If *close* is set to ``True`` then the underlying stream will be closed
automatically when the :class:`deflate.DeflateIO` stream is closed. This is
useful if you want to return a :class:`deflate.DeflateIO` stream that wraps
another stream and not have the caller need to know about managing the
underlying stream.
If compression is enabled, a given :class:`deflate.DeflateIO` instance
supports both reading and writing. For example, a bidirectional stream like
a socket can be wrapped, which allows for compression/decompression in both
directions.
Constants
---------
.. data:: deflate.AUTO
deflate.RAW
deflate.ZLIB
deflate.GZIP
Supported values for the *format* parameter.
Examples
--------
A typical use case for :class:`deflate.DeflateIO` is to read or write a compressed
file from storage:
.. code:: python
import deflate
# Writing a zlib-compressed stream (uses the default window size of 256 bytes).
with open("data.gz", "wb") as f:
with deflate.DeflateIO(f, deflate.ZLIB) as d:
# Use d.write(...) etc
# Reading a zlib-compressed stream (auto-detect window size).
with open("data.z", "rb") as f:
with deflate.DeflateIO(f, deflate.ZLIB) as d:
# Use d.read(), d.readinto(), etc.
Because :class:`deflate.DeflateIO` is a stream, it can be used for example
with :meth:`json.dump` and :meth:`json.load` (and any other places streams can
be used):
.. code:: python
import deflate, json
# Write a dictionary as JSON in gzip format, with a
# small (64 byte) window size.
config = { ... }
with open("config.gz", "wb") as f:
with deflate.DeflateIO(f, deflate.GZIP, 6) as f:
json.dump(config, f)
# Read back that dictionary.
with open("config.gz", "rb") as f:
with deflate.DeflateIO(f, deflate.GZIP, 6) as f:
config = json.load(f)
If your source data is not in a stream format, you can use :class:`io.BytesIO`
to turn it into a stream suitable for use with :class:`deflate.DeflateIO`:
.. code:: python
import deflate, io
# Decompress a bytes/bytearray value.
compressed_data = get_data_z()
with deflate.DeflateIO(io.BytesIO(compressed_data), deflate.ZLIB) as d:
decompressed_data = d.read()
# Compress a bytes/bytearray value.
uncompressed_data = get_data()
stream = io.BytesIO()
with deflate.DeflateIO(stream, deflate.ZLIB) as d:
d.write(uncompressed_data)
compressed_data = stream.getvalue()
.. _deflate_wbits:
Deflate window size
-------------------
The window size limits how far back in the stream the (de)compressor can
reference. Increasing the window size will improve compression, but will require
more memory and make the compressor slower.
If an input stream was compressed a given window size, then `DeflateIO`
using a smaller window size will fail mid-way during decompression with
:exc:`OSError`, but only if a back-reference actually refers back further
than the decompressor's window size. This means it may be possible to decompress
with a smaller window size. For example, this would trivially be the case if the
original uncompressed data is shorter than the window size.
Decompression
~~~~~~~~~~~~~
The zlib format includes a header which specifies the window size that was used
to compress the data. This indicates the maximum window size required to
decompress this stream. If this header value is less than the specified *wbits*
value (or if *wbits* is unset), then the header value will be used.
The gzip format does not include the window size in the header, and assumes that
all gzip compressors (e.g. the ``gzip`` utility, or CPython's implementation of
:class:`gzip.GzipFile`) use the maximum window size of 32kiB. For this reason,
if the *wbits* parameter is not set, the decompressor will use a 32 kiB window
size (corresponding to *wbits* set to 15). This means that to be able to
decompress an arbitrary gzip stream, you must have at least this much RAM
available. If you control the source data, consider instead using the zlib
format with a smaller window size.
The raw format has no header and therefore does not include any information
about the window size. If *wbits* is not set, then it will default to a window
size of 256 bytes, which may not be large enough for a given stream. Therefore
it is recommended that you should always explicitly set *wbits* if using the raw
format.
Compression
~~~~~~~~~~~
For compression, MicroPython will default to a window size of 256 bytes for all
formats. This provides a reasonable amount of compression with minimal memory
usage and fast compression time, and will generate output that will work with
any decompressor.

View File

@ -62,12 +62,35 @@ Functions
.. function:: flash_erase(sector_no)
.. function:: osdebug(level)
.. function:: osdebug(uart_no)
Turn esp os debugging messages on or off.
.. note:: This is the ESP8266 form of this function.
The *level* parameter sets the threshold for the log messages for all esp components.
The log levels are defined as constants:
Change the level of OS serial debug log messages. On boot,
OS serial debug log messages are disabled.
``uart_no`` is the number of the UART peripheral which should receive
OS-level output, or ``None`` to disable OS serial debug log messages.
.. function:: osdebug(uart_no, [level])
:no-index:
.. note:: This is the ESP32 form of this function.
Change the level of OS serial debug log messages. On boot, OS
serial debug log messages are limited to Error output only.
The behaviour of this function depends on the arguments passed to it. The
following combinations are supported:
``osdebug(None)`` restores the default OS debug log message level
(``LOG_ERROR``).
``osdebug(0)`` enables all available OS debug log messages (in the
default build configuration this is ``LOG_INFO``).
``osdebug(0, level)`` sets the OS debug log message level to the
specified value. The log levels are defined as constants:
* ``LOG_NONE`` -- No log output
* ``LOG_ERROR`` -- Critical errors, software module can not recover on its own
@ -77,6 +100,15 @@ Functions
* ``LOG_VERBOSE`` -- Bigger chunks of debugging information, or frequent messages
which can potentially flood the output
.. note:: ``LOG_DEBUG`` and ``LOG_VERBOSE`` are not compiled into the
MicroPython binary by default, to save size. A custom build with a
modified "``sdkconfig``" source file is needed to see any output
at these log levels.
.. note:: Log output on ESP32 is automatically suspended in "Raw REPL" mode,
to prevent communications issues. This means OS level logging is never
seen when using ``mpremote run`` and similar tools.
.. function:: set_native_code_location(start, length)
**Note**: ESP8266 only

View File

@ -44,10 +44,6 @@ Functions
Read the raw value of the internal temperature sensor, returning an integer.
.. function:: hall_sensor()
Read the raw value of the internal Hall sensor, returning an integer.
.. function:: idf_heap_info(capabilities)
Returns information about the ESP-IDF heap memory regions. One of them contains
@ -55,8 +51,6 @@ Functions
buffers and other data. This data is useful to get a sense of how much memory
is available to ESP-IDF and the networking stack in particular. It may shed
some light on situations where ESP-IDF operations fail due to allocation failures.
The information returned is *not* useful to troubleshoot Python allocation failures,
use `micropython.mem_info()` instead.
The capabilities parameter corresponds to ESP-IDF's ``MALLOC_CAP_XXX`` values but the
two most useful ones are predefined as `esp32.HEAP_DATA` for data heap regions and
@ -72,6 +66,21 @@ Functions
[(240, 0, 0, 0), (7288, 0, 0, 0), (16648, 4, 4, 4), (79912, 35712, 35512, 35108),
(15072, 15036, 15036, 15036), (113840, 0, 0, 0)]
.. note:: Free IDF heap memory in the `esp32.HEAP_DATA` region is available
to be automatically added to the MicroPython heap to prevent a
MicroPython allocation from failing. However, the information returned
here is otherwise *not* useful to troubleshoot Python allocation
failures. :func:`micropython.mem_info()` and :func:`gc.mem_free()` should
be used instead:
The "max new split" value in :func:`micropython.mem_info()` output
corresponds to the largest free block of ESP-IDF heap that could be
automatically added on demand to the MicroPython heap.
The result of :func:`gc.mem_free()` is the total of the current "free"
and "max new split" values printed by :func:`micropython.mem_info()`.
Flash partitions
----------------
@ -111,6 +120,11 @@ methods to enable over-the-air (OTA) updates.
Sets the partition as the boot partition.
.. note:: Do not enter :func:`deepsleep<machine.deepsleep>` after changing
the OTA boot partition, without first performing a hard
:func:`reset<machine.reset>` or power cycle. This ensures the bootloader
will validate the new image before booting.
.. method:: Partition.get_next_update()
Gets the next update partition after this one, and returns a new Partition object.
@ -126,7 +140,7 @@ methods to enable over-the-air (OTA) updates.
and an ``OSError(-261)`` is raised if called on firmware that doesn't have the
feature enabled.
It is OK to call ``mark_app_valid_cancel_rollback`` on every boot and it is not
necessary when booting firmare that was loaded using esptool.
necessary when booting firmware that was loaded using esptool.
Constants
~~~~~~~~~
@ -179,7 +193,7 @@ numbers specified in ``write_pulses`` are multiplied by the resolution to
define the pulses.
``clock_div`` is an 8-bit divider (0-255) and each pulse can be defined by
multiplying the resolution by a 15-bit (0-32,768) number. There are eight
multiplying the resolution by a 15-bit (1-``PULSE_MAX``) number. There are eight
channels (0-7) and each can have a different clock divider.
So, in the example above, the 80MHz clock is divided by 8. Thus the
@ -212,7 +226,7 @@ For more details see Espressif's `ESP-IDF RMT documentation.
``100``) and the output level to apply the carrier to (a boolean as per
*idle_level*).
.. method:: RMT.source_freq()
.. classmethod:: RMT.source_freq()
Returns the source clock frequency. Currently the source clock is not
configurable so this will always return 80MHz.
@ -250,10 +264,10 @@ For more details see Espressif's `ESP-IDF RMT documentation.
**Mode 3:** *duration* and *data* are lists or tuples of equal length,
specifying individual durations and the output level for each.
Durations are in integer units of the channel resolution (as described
above), between 1 and 32767 units. Output levels are any value that can
be converted to a boolean, with ``True`` representing high voltage and
``False`` representing low.
Durations are in integer units of the channel resolution (as
described above), between 1 and ``PULSE_MAX`` units. Output levels
are any value that can be converted to a boolean, with ``True``
representing high voltage and ``False`` representing low.
If transmission of an earlier sequence is in progress then this method will
block until that transmission is complete before beginning the new sequence.
@ -276,9 +290,24 @@ For more details see Espressif's `ESP-IDF RMT documentation.
Passing in no argument will not change the channel. This function returns
the current channel number.
Constants
---------
.. data:: RMT.PULSE_MAX
Maximum integer that can be set for a pulse duration.
Ultra-Low-Power co-processor
----------------------------
This class gives access to the Ultra Low Power (ULP) co-processor on the ESP32,
ESP32-S2 and ESP32-S3 chips.
.. warning::
This class does not provide access to the RISCV ULP co-processor available
on the ESP32-S2 and ESP32-S3 chips.
.. class:: ULP()
This class provides access to the Ultra-Low-Power co-processor.

936
docs/library/espnow.rst Normal file
View File

@ -0,0 +1,936 @@
:mod:`espnow` --- support for the ESP-NOW wireless protocol
===========================================================
.. module:: espnow
:synopsis: ESP-NOW wireless protocol support
This module provides an interface to the `ESP-NOW <https://www.espressif.com/
en/products/software/esp-now/overview>`_ protocol provided by Espressif on
ESP32 and ESP8266 devices (`API docs <https://docs.espressif.com/
projects/esp-idf/en/latest/api-reference/network/esp_now.html>`_).
Table of Contents:
------------------
- `Introduction`_
- `Configuration`_
- `Sending and Receiving Data`_
- `Peer Management`_
- `Callback Methods`_
- `Exceptions`_
- `Constants`_
- `Wifi Signal Strength (RSSI) - (ESP32 Only)`_
- `Supporting asyncio`_
- `Broadcast and Multicast`_
- `ESPNow and Wifi Operation`_
- `ESPNow and Sleep Modes`_
Introduction
------------
ESP-NOW is a connection-less wireless communication protocol supporting:
- Direct communication between up to 20 registered peers:
- Without the need for a wireless access point (AP),
- Encrypted and unencrypted communication (up to 6 encrypted peers),
- Message sizes up to 250 bytes,
- Can operate alongside Wifi operation (:doc:`network.WLAN<network.WLAN>`) on
ESP32 and ESP8266 devices.
It is especially useful for small IoT networks, latency sensitive or power
sensitive applications (such as battery operated devices) and for long-range
communication between devices (hundreds of metres).
This module also supports tracking the Wifi signal strength (RSSI) of peer
devices.
A simple example would be:
**Sender:** ::
import network
import espnow
# A WLAN interface must be active to send()/recv()
sta = network.WLAN(network.STA_IF) # Or network.AP_IF
sta.active(True)
sta.disconnect() # For ESP8266
e = espnow.ESPNow()
e.active(True)
peer = b'\xbb\xbb\xbb\xbb\xbb\xbb' # MAC address of peer's wifi interface
e.add_peer(peer) # Must add_peer() before send()
e.send(peer, "Starting...")
for i in range(100):
e.send(peer, str(i)*20, True)
e.send(peer, b'end')
**Receiver:** ::
import network
import espnow
# A WLAN interface must be active to send()/recv()
sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.disconnect() # Because ESP8266 auto-connects to last Access Point
e = espnow.ESPNow()
e.active(True)
while True:
host, msg = e.recv()
if msg: # msg == None if timeout in recv()
print(host, msg)
if msg == b'end':
break
class ESPNow
------------
Constructor
-----------
.. class:: ESPNow()
Returns the singleton ESPNow object. As this is a singleton, all calls to
`espnow.ESPNow()` return a reference to the same object.
.. note::
Some methods are available only on the ESP32 due to code size
restrictions on the ESP8266 and differences in the Espressif API.
Configuration
-------------
.. method:: ESPNow.active([flag])
Initialise or de-initialise the ESP-NOW communication protocol depending on
the value of the ``flag`` optional argument.
.. data:: Arguments:
- *flag*: Any python value which can be converted to a boolean type.
- ``True``: Prepare the software and hardware for use of the ESP-NOW
communication protocol, including:
- initialise the ESPNow data structures,
- allocate the recv data buffer,
- invoke esp_now_init() and
- register the send and recv callbacks.
- ``False``: De-initialise the Espressif ESP-NOW software stack
(esp_now_deinit()), disable callbacks, deallocate the recv
data buffer and deregister all peers.
If *flag* is not provided, return the current status of the ESPNow
interface.
.. data:: Returns:
``True`` if interface is currently *active*, else ``False``.
.. method:: ESPNow.config(param=value, ...)
ESPNow.config('param') (ESP32 only)
Set or get configuration values of the ESPNow interface. To set values, use
the keyword syntax, and one or more parameters can be set at a time. To get
a value the parameter name should be quoted as a string, and just one
parameter is queried at a time.
**Note:** *Getting* parameters is not supported on the ESP8266.
.. data:: Options:
*rxbuf*: (default=526) Get/set the size in bytes of the internal
buffer used to store incoming ESPNow packet data. The default size is
selected to fit two max-sized ESPNow packets (250 bytes) with associated
mac_address (6 bytes), a message byte count (1 byte) and RSSI data plus
buffer overhead. Increase this if you expect to receive a lot of large
packets or expect bursty incoming traffic.
**Note:** The recv buffer is allocated by `ESPNow.active()`. Changing
this value will have no effect until the next call of
`ESPNow.active(True)<ESPNow.active()>`.
*timeout_ms*: (default=300,000) Default timeout (in milliseconds)
for receiving ESPNow messages. If *timeout_ms* is less than zero, then
wait forever. The timeout can also be provided as arg to
`recv()`/`irecv()`/`recvinto()`.
*rate*: (ESP32 only, IDF>=4.3.0 only) Set the transmission speed for
ESPNow packets. Must be set to a number from the allowed numeric values
in `enum wifi_phy_rate_t
<https://docs.espressif.com/projects/esp-idf/en/v4.4.1/esp32/
api-reference/network/esp_wifi.html#_CPPv415wifi_phy_rate_t>`_.
.. data:: Returns:
``None`` or the value of the parameter being queried.
.. data:: Raises:
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised.
- ``ValueError()`` on invalid configuration options or values.
Sending and Receiving Data
--------------------------
A wifi interface (``network.STA_IF`` or ``network.AP_IF``) must be
`active()<network.WLAN.active>` before messages can be sent or received,
but it is not necessary to connect or configure the WLAN interface.
For example::
import network
sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.disconnect() # For ESP8266
**Note:** The ESP8266 has a *feature* that causes it to automatically reconnect
to the last wifi Access Point when set `active(True)<network.WLAN.active>` (even
after reboot/reset). This reduces the reliability of receiving ESP-NOW messages
(see `ESPNow and Wifi Operation`_). You can avoid this by calling
`disconnect()<network.WLAN.disconnect>` after
`active(True)<network.WLAN.active>`.
.. method:: ESPNow.send(mac, msg[, sync])
ESPNow.send(msg) (ESP32 only)
Send the data contained in ``msg`` to the peer with given network ``mac``
address. In the second form, ``mac=None`` and ``sync=True``. The peer must
be registered with `ESPNow.add_peer()<ESPNow.add_peer()>` before the
message can be sent.
.. data:: Arguments:
- *mac*: byte string exactly ``espnow.ADDR_LEN`` (6 bytes) long or
``None``. If *mac* is ``None`` (ESP32 only) the message will be sent
to all registered peers, except any broadcast or multicast MAC
addresses.
- *msg*: string or byte-string up to ``espnow.MAX_DATA_LEN`` (250)
bytes long.
- *sync*:
- ``True``: (default) send ``msg`` to the peer(s) and wait for a
response (or not).
- ``False`` send ``msg`` and return immediately. Responses from the
peers will be discarded.
.. data:: Returns:
``True`` if ``sync=False`` or if ``sync=True`` and *all* peers respond,
else ``False``.
.. data:: Raises:
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised.
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_FOUND")`` if peer is not registered.
- ``OSError(num, "ESP_ERR_ESPNOW_IF")`` the wifi interface is not
`active()<network.WLAN.active>`.
- ``OSError(num, "ESP_ERR_ESPNOW_NO_MEM")`` internal ESP-NOW buffers are
full.
- ``ValueError()`` on invalid values for the parameters.
**Note**: A peer will respond with success if its wifi interface is
`active()<network.WLAN.active>` and set to the same channel as the sender,
regardless of whether it has initialised it's ESP-NOW system or is
actively listening for ESP-NOW traffic (see the Espressif ESP-NOW docs).
.. method:: ESPNow.recv([timeout_ms])
Wait for an incoming message and return the ``mac`` address of the peer and
the message. **Note**: It is **not** necessary to register a peer (using
`add_peer()<ESPNow.add_peer()>`) to receive a message from that peer.
.. data:: Arguments:
- *timeout_ms*: (Optional): May have the following values.
- ``0``: No timeout. Return immediately if no data is available;
- ``> 0``: Specify a timeout value in milliseconds;
- ``< 0``: Do not timeout, ie. wait forever for new messages; or
- ``None`` (or not provided): Use the default timeout value set with
`ESPNow.config()`.
.. data:: Returns:
- ``(None, None)`` if timeout is reached before a message is received, or
- ``[mac, msg]``: where:
- ``mac`` is a bytestring containing the address of the device which
sent the message, and
- ``msg`` is a bytestring containing the message.
.. data:: Raises:
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised.
- ``OSError(num, "ESP_ERR_ESPNOW_IF")`` if the wifi interface is not
`active()<network.WLAN.active>`.
- ``ValueError()`` on invalid *timeout_ms* values.
`ESPNow.recv()` will allocate new storage for the returned list and the
``peer`` and ``msg`` bytestrings. This can lead to memory fragmentation if
the data rate is high. See `ESPNow.irecv()` for a memory-friendly
alternative.
.. method:: ESPNow.irecv([timeout_ms])
Works like `ESPNow.recv()` but will reuse internal bytearrays to store the
return values: ``[mac, msg]``, so that no new memory is allocated on each
call.
.. data:: Arguments:
*timeout_ms*: (Optional) Timeout in milliseconds (see `ESPNow.recv()`).
.. data:: Returns:
- As for `ESPNow.recv()`, except that ``msg`` is a bytearray, instead of
a bytestring. On the ESP8266, ``mac`` will also be a bytearray.
.. data:: Raises:
- See `ESPNow.recv()`.
**Note:** You may also read messages by iterating over the ESPNow object,
which will use the `irecv()` method for alloc-free reads, eg: ::
import espnow
e = espnow.ESPNow(); e.active(True)
for mac, msg in e:
print(mac, msg)
if mac is None: # mac, msg will equal (None, None) on timeout
break
.. method:: ESPNow.recvinto(data[, timeout_ms])
Wait for an incoming message and return the length of the message in bytes.
This is the low-level method used by both `recv()<ESPNow.recv()>` and
`irecv()` to read messages.
.. data:: Arguments:
*data*: A list of at least two elements, ``[peer, msg]``. ``msg`` must
be a bytearray large enough to hold the message (250 bytes). On the
ESP8266, ``peer`` should be a bytearray of 6 bytes. The MAC address of
the sender and the message will be stored in these bytearrays (see Note
on ESP32 below).
*timeout_ms*: (Optional) Timeout in milliseconds (see `ESPNow.recv()`).
.. data:: Returns:
- Length of message in bytes or 0 if *timeout_ms* is reached before a
message is received.
.. data:: Raises:
- See `ESPNow.recv()`.
**Note:** On the ESP32:
- It is unnecessary to provide a bytearray in the first element of the
``data`` list because it will be replaced by a reference to a unique
``peer`` address in the **peer device table** (see `ESPNow.peers_table`).
- If the list is at least 4 elements long, the rssi and timestamp values
will be saved as the 3rd and 4th elements.
.. method:: ESPNow.any()
Check if data is available to be read with `ESPNow.recv()`.
For more sophisticated querying of available characters use `select.poll()`::
import select
import espnow
e = espnow.ESPNow()
poll = select.poll()
poll.register(e, select.POLLIN)
poll.poll(timeout)
.. data:: Returns:
``True`` if data is available to be read, else ``False``.
.. method:: ESPNow.stats() (ESP32 only)
.. data:: Returns:
A 5-tuple containing the number of packets sent/received/lost:
``(tx_pkts, tx_responses, tx_failures, rx_packets, rx_dropped_packets)``
Incoming packets are *dropped* when the recv buffers are full. To reduce
packet loss, increase the ``rxbuf`` config parameters and ensure you are
reading messages as quickly as possible.
**Note**: Dropped packets will still be acknowledged to the sender as
received.
Peer Management
---------------
On ESP32 devices, the Espressif ESP-NOW software requires that other devices
(peers) must be *registered* using `add_peer()` before we can
`send()<ESPNow.send()>` them messages (this is *not* enforced on ESP8266
devices). It is **not** necessary to register a peer to receive an
un-encrypted message from that peer.
**Encrypted messages**: To receive an *encrypted* message, the receiving device
must first register the sender and use the same encryption keys as the sender
(PMK and LMK) (see `set_pmk()` and `add_peer()`.
.. method:: ESPNow.set_pmk(pmk)
Set the Primary Master Key (PMK) which is used to encrypt the Local Master
Keys (LMK) for encrypting messages. If this is not set, a default PMK is
used by the underlying Espressif ESP-NOW software stack.
**Note:** messages will only be encrypted if *lmk* is also set in
`ESPNow.add_peer()` (see `Security
<https://docs.espressif.com/projects/esp-idf/en/latest/
esp32/api-reference/network/esp_now.html#security>`_ in the Espressif API
docs).
.. data:: Arguments:
*pmk*: Must be a byte string, bytearray or string of length
`espnow.KEY_LEN` (16 bytes).
.. data:: Returns:
``None``
.. data:: Raises:
``ValueError()`` on invalid *pmk* values.
.. method:: ESPNow.add_peer(mac, [lmk], [channel], [ifidx], [encrypt])
ESPNow.add_peer(mac, param=value, ...) (ESP32 only)
Add/register the provided *mac* address as a peer. Additional parameters may
also be specified as positional or keyword arguments (any parameter set to
``None`` will be set to it's default value):
.. data:: Arguments:
- *mac*: The MAC address of the peer (as a 6-byte byte-string).
- *lmk*: The Local Master Key (LMK) key used to encrypt data
transfers with this peer (unless the *encrypt* parameter is set to
``False``). Must be:
- a byte-string or bytearray or string of length ``espnow.KEY_LEN``
(16 bytes), or
- any non ``True`` python value (default= ``b''``), signifying an
*empty* key which will disable encryption.
- *channel*: The wifi channel (2.4GHz) to communicate with this peer.
Must be an integer from 0 to 14. If channel is set to 0 the current
channel of the wifi device will be used. (default=0)
- *ifidx*: (ESP32 only) Index of the wifi interface which will be
used to send data to this peer. Must be an integer set to
``network.STA_IF`` (=0) or ``network.AP_IF`` (=1).
(default=0/``network.STA_IF``). See `ESPNow and Wifi Operation`_
below for more information.
- *encrypt*: (ESP32 only) If set to ``True`` data exchanged with
this peer will be encrypted with the PMK and LMK. (default =
``True`` if *lmk* is set to a valid key, else ``False``)
**ESP8266**: Keyword args may not be used on the ESP8266.
**Note:** The maximum number of peers which may be registered is 20
(`espnow.MAX_TOTAL_PEER_NUM`), with a maximum of 6
(`espnow.MAX_ENCRYPT_PEER_NUM`) of those peers with encryption enabled
(see `ESP_NOW_MAX_ENCRYPT_PEER_NUM <https://docs.espressif.com/
projects/esp-idf/en/latest/esp32/api-reference/network/
esp_now.html#c.ESP_NOW_MAX_ENCRYPT_PEER_NUM>`_ in the Espressif API
docs).
.. data:: Raises:
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised.
- ``OSError(num, "ESP_ERR_ESPNOW_EXIST")`` if *mac* is already
registered.
- ``OSError(num, "ESP_ERR_ESPNOW_FULL")`` if too many peers are
already registered.
- ``ValueError()`` on invalid keyword args or values.
.. method:: ESPNow.del_peer(mac)
Deregister the peer associated with the provided *mac* address.
.. data:: Returns:
``None``
.. data:: Raises:
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised.
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_FOUND")`` if *mac* is not
registered.
- ``ValueError()`` on invalid *mac* values.
.. method:: ESPNow.get_peer(mac) (ESP32 only)
Return information on a registered peer.
.. data:: Returns:
``(mac, lmk, channel, ifidx, encrypt)``: a tuple of the "peer
info" associated with the given *mac* address.
.. data:: Raises:
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised.
- ``OSError(num, "ESP_ERR_ESPNOW_NOT_FOUND")`` if *mac* is not
registered.
- ``ValueError()`` on invalid *mac* values.
.. method:: ESPNow.peer_count() (ESP32 only)
Return the number of registered peers:
- ``(peer_num, encrypt_num)``: where
- ``peer_num`` is the number of peers which are registered, and
- ``encrypt_num`` is the number of encrypted peers.
.. method:: ESPNow.get_peers() (ESP32 only)
Return the "peer info" parameters for all the registered peers (as a tuple
of tuples).
.. method:: ESPNow.mod_peer(mac, lmk, [channel], [ifidx], [encrypt]) (ESP32 only)
ESPNow.mod_peer(mac, 'param'=value, ...) (ESP32 only)
Modify the parameters of the peer associated with the provided *mac*
address. Parameters may be provided as positional or keyword arguments
(see `ESPNow.add_peer()`). Any parameter that is not set (or set to
``None``) will retain the existing value for that parameter.
Callback Methods
----------------
.. method:: ESPNow.irq(callback) (ESP32 only)
Set a callback function to be called *as soon as possible* after a message has
been received from another ESPNow device. The callback function will be called
with the `ESPNow` instance object as an argument. For more reliable operation,
it is recommended to read out as many messages as are available when the
callback is invoked and to set the read timeout to zero, eg: ::
def recv_cb(e):
while True: # Read out all messages waiting in the buffer
mac, msg = e.irecv(0) # Don't wait if no messages left
if mac is None:
return
print(mac, msg)
e.irq(recv_cb)
The `irq()<ESPNow.irq()>` callback method is an alternative method for
processing incoming messages, especially if the data rate is moderate
and the device is *not too busy* but there are some caveats:
- The scheduler stack *can* overflow and callbacks will be missed if
packets are arriving at a sufficient rate or if other MicroPython components
(eg, bluetooth, machine.Pin.irq(), machine.timer, i2s, ...) are exercising
the scheduler stack. This method may be less reliable for dealing with
bursts of messages, or high throughput or on a device which is busy dealing
with other hardware operations.
- For more information on *scheduled* function callbacks see:
`micropython.schedule()<micropython.schedule>`.
Constants
---------
.. data:: espnow.MAX_DATA_LEN(=250)
espnow.KEY_LEN(=16)
espnow.ADDR_LEN(=6)
espnow.MAX_TOTAL_PEER_NUM(=20)
espnow.MAX_ENCRYPT_PEER_NUM(=6)
Exceptions
----------
If the underlying Espressif ESP-NOW software stack returns an error code,
the MicroPython espnow module will raise an ``OSError(errnum, errstring)``
exception where ``errstring`` is set to the name of one of the error codes
identified in the
`Espressif ESP-NOW docs
<https://docs.espressif.com/projects/esp-idf/en/latest/
api-reference/network/esp_now.html#api-reference>`_. For example::
try:
e.send(peer, 'Hello')
except OSError as err:
if len(err.args) < 2:
raise err
if err.args[1] == 'ESP_ERR_ESPNOW_NOT_INIT':
e.active(True)
elif err.args[1] == 'ESP_ERR_ESPNOW_NOT_FOUND':
e.add_peer(peer)
elif err.args[1] == 'ESP_ERR_ESPNOW_IF':
network.WLAN(network.STA_IF).active(True)
else:
raise err
Wifi Signal Strength (RSSI) - (ESP32 only)
------------------------------------------
The ESPNow object maintains a **peer device table** which contains the signal
strength and timestamp of the last received message from all hosts. The **peer
device table** can be accessed using `ESPNow.peers_table` and can be used to
track device proximity and identify *nearest neighbours* in a network of peer
devices. This feature is **not** available on ESP8266 devices.
.. data:: ESPNow.peers_table
A reference to the **peer device table**: a dict of known peer devices
and rssi values::
{peer: [rssi, time_ms], ...}
where:
- ``peer`` is the peer MAC address (as `bytes`);
- ``rssi`` is the wifi signal strength in dBm (-127 to 0) of the last
message received from the peer; and
- ``time_ms`` is the time the message was received (in milliseconds since
system boot - wraps every 12 days).
Example::
>>> e.peers_table
{b'\xaa\xaa\xaa\xaa\xaa\xaa': [-31, 18372],
b'\xbb\xbb\xbb\xbb\xbb\xbb': [-43, 12541]}
**Note**: the ``mac`` addresses returned by `recv()` are references to
the ``peer`` key values in the **peer device table**.
**Note**: RSSI and timestamp values in the device table are updated only
when the message is read by the application.
Supporting asyncio
------------------
A supplementary module (`aioespnow`) is available to provide
:doc:`asyncio<asyncio>` support.
**Note:** Asyncio support is available on all ESP32 targets as well as those
ESP8266 boards which include the asyncio module (ie. ESP8266 devices with at
least 2MB flash memory).
A small async server example::
import network
import aioespnow
import asyncio
# A WLAN interface must be active to send()/recv()
network.WLAN(network.STA_IF).active(True)
e = aioespnow.AIOESPNow() # Returns AIOESPNow enhanced with async support
e.active(True)
peer = b'\xbb\xbb\xbb\xbb\xbb\xbb'
e.add_peer(peer)
# Send a periodic ping to a peer
async def heartbeat(e, peer, period=30):
while True:
if not await e.asend(peer, b'ping'):
print("Heartbeat: peer not responding:", peer)
else:
print("Heartbeat: ping", peer)
await asyncio.sleep(period)
# Echo any received messages back to the sender
async def echo_server(e):
async for mac, msg in e:
print("Echo:", msg)
try:
await e.asend(mac, msg)
except OSError as err:
if len(err.args) > 1 and err.args[1] == 'ESP_ERR_ESPNOW_NOT_FOUND':
e.add_peer(mac)
await e.asend(mac, msg)
async def main(e, peer, timeout, period):
asyncio.create_task(heartbeat(e, peer, period))
asyncio.create_task(echo_server(e))
await asyncio.sleep(timeout)
asyncio.run(main(e, peer, 120, 10))
.. module:: aioespnow
:synopsis: ESP-NOW :doc:`asyncio` support
.. class:: AIOESPNow()
The `AIOESPNow` class inherits all the methods of `ESPNow<espnow.ESPNow>`
and extends the interface with the following async methods.
.. method:: async AIOESPNow.arecv()
Asyncio support for `ESPNow.recv()`. Note that this method does not take a
timeout value as argument.
.. method:: async AIOESPNow.airecv()
Asyncio support for `ESPNow.irecv()`. Note that this method does not take a
timeout value as argument.
.. method:: async AIOESPNow.asend(mac, msg, sync=True)
async AIOESPNow.asend(msg)
Asyncio support for `ESPNow.send()`.
.. method:: AIOESPNow._aiter__() / async AIOESPNow.__anext__()
`AIOESPNow` also supports reading incoming messages by asynchronous
iteration using ``async for``; eg::
e = AIOESPNow()
e.active(True)
async def recv_till_halt(e):
async for mac, msg in e:
print(mac, msg)
if msg == b'halt':
break
asyncio.run(recv_till_halt(e))
Broadcast and Multicast
-----------------------
All active ESPNow clients will receive messages sent to their MAC address and
all devices (**except ESP8266 devices**) will also receive messages sent to the
*broadcast* MAC address (``b'\xff\xff\xff\xff\xff\xff'``) or any multicast
MAC address.
All ESPNow devices (including ESP8266 devices) can also send messages to the
broadcast MAC address or any multicast MAC address.
To `send()<ESPNow.send()>` a broadcast message, the broadcast (or
multicast) MAC address must first be registered using
`add_peer()<ESPNow.add_peer()>`. `send()<ESPNow.send()>` will always return
``True`` for broadcasts, regardless of whether any devices receive the
message. It is not permitted to encrypt messages sent to the broadcast
address or any multicast address.
**Note**: `ESPNow.send(None, msg)<ESPNow.send()>` will send to all registered
peers *except* the broadcast address. To send a broadcast or multicast
message, you must specify the broadcast (or multicast) MAC address as the
peer. For example::
bcast = b'\xff' * 6
e.add_peer(bcast)
e.send(bcast, "Hello World!")
ESPNow and Wifi Operation
-------------------------
ESPNow messages may be sent and received on any `active()<network.WLAN.active>`
`WLAN<network.WLAN()>` interface (``network.STA_IF`` or ``network.AP_IF``), even
if that interface is also connected to a wifi network or configured as an access
point. When an ESP32 or ESP8266 device connects to a Wifi Access Point (see
`ESP32 Quickref <../esp32/quickref.html#networking>`__) the following things
happen which affect ESPNow communications:
1. Wifi Power-saving Mode (`network.WLAN.PM_PERFORMANCE`)
is automatically activated and
2. The radio on the esp device changes wifi ``channel`` to match the channel
used by the Access Point.
**Wifi Power-saving Mode:** (see `Espressif Docs <https://docs.espressif.com/
projects/esp-idf/en/latest/esp32/api-guides/
wifi.html#esp32-wi-fi-power-saving-mode>`_) The power saving mode causes the
device to turn off the radio periodically (typically for hundreds of
milliseconds), making it unreliable in receiving ESPNow messages. This can be
resolved by either of:
1. Disabling the power-saving mode on the STA_IF interface;
- Use ``sta.config(pm=sta.PM_NONE)``
2. Turning on the AP_IF interface, which will disable the power saving mode.
However, the device will then be advertising an active wifi access point.
- You **may** also choose to send your messages via the AP_IF interface, but
this is not necessary.
- ESP8266 peers must send messages to this AP_IF interface (see below).
3. Configuring ESPNow clients to retry sending messages.
**Receiving messages from an ESP8266 device:** Strangely, an ESP32 device
connected to a wifi network using method 1 or 2 above, will receive ESPNow
messages sent to the STA_IF MAC address from another ESP32 device, but will
**reject** messages from an ESP8266 device!!!. To receive messages from an
ESP8266 device, the AP_IF interface must be set to ``active(True)`` **and**
messages must be sent to the AP_IF MAC address.
**Managing wifi channels:** Any other ESPNow devices wishing to communicate with
a device which is also connected to a Wifi Access Point MUST use the same
channel. A common scenario is where one ESPNow device is connected to a wifi
router and acts as a proxy for messages from a group of sensors connected via
ESPNow:
**Proxy:** ::
import network, time, espnow
sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected
sta.connect('myssid', 'mypassword')
while not sta.isconnected(): # Wait until connected...
time.sleep(0.1)
sta.config(pm=sta.PM_NONE) # ..then disable power saving
# Print the wifi channel used AFTER finished connecting to access point
print("Proxy running on channel:", sta.config("channel"))
e = espnow.ESPNow(); e.active(True)
for peer, msg in e:
# Receive espnow messages and forward them to MQTT broker over wifi
**Sensor:** ::
import network, espnow
sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected
sta.config(channel=6) # Change to the channel used by the proxy above.
peer = b'0\xaa\xaa\xaa\xaa\xaa' # MAC address of proxy
e = espnow.ESPNow(); e.active(True);
e.add_peer(peer)
while True:
msg = read_sensor()
e.send(peer, msg)
time.sleep(1)
Other issues to take care with when using ESPNow with wifi are:
- **Set WIFI to known state on startup:** MicroPython does not reset the wifi
peripheral after a soft reset. This can lead to unexpected behaviour. To
guarantee the wifi is reset to a known state after a soft reset make sure you
deactivate the STA_IF and AP_IF before setting them to the desired state at
startup, eg.::
import network, time
def wifi_reset(): # Reset wifi to AP_IF off, STA_IF on and disconnected
sta = network.WLAN(network.STA_IF); sta.active(False)
ap = network.WLAN(network.AP_IF); ap.active(False)
sta.active(True)
while not sta.active():
time.sleep(0.1)
sta.disconnect() # For ESP8266
while sta.isconnected():
time.sleep(0.1)
return sta, ap
sta, ap = wifi_reset()
Remember that a soft reset occurs every time you connect to the device REPL
and when you type ``ctrl-D``.
- **STA_IF and AP_IF always operate on the same channel:** the AP_IF will change
channel when you connect to a wifi network; regardless of the channel you set
for the AP_IF (see `Attention Note 3
<https://docs.espressif.com/
projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html
#_CPPv419esp_wifi_set_config16wifi_interface_tP13wifi_config_t>`_
). After all, there is really only one wifi radio on the device, which is
shared by the STA_IF and AP_IF virtual devices.
- **Disable automatic channel assignment on your wifi router:** If the wifi
router for your wifi network is configured to automatically assign the wifi
channel, it may change the channel for the network if it detects interference
from other wifi routers. When this occurs, the ESP devices connected to the
wifi network will also change channels to match the router, but other
ESPNow-only devices will remain on the previous channel and communication will
be lost. To mitigate this, either set your wifi router to use a fixed wifi
channel or configure your devices to re-scan the wifi channels if they are
unable to find their expected peers on the current channel.
- **MicroPython re-scans wifi channels when trying to reconnect:** If the esp
device is connected to a Wifi Access Point that goes down, MicroPython will
automatically start scanning channels in an attempt to reconnect to the
Access Point. This means ESPNow messages will be lost while scanning for the
AP. This can be disabled by ``sta.config(reconnects=0)``, which will also
disable the automatic reconnection after losing connection.
- Some versions of the ESP IDF only permit sending ESPNow packets from the
STA_IF interface to peers which have been registered on the same wifi
channel as the STA_IF::
ESPNOW: Peer channel is not equal to the home channel, send fail!
ESPNow and Sleep Modes
----------------------
The `machine.lightsleep([time_ms])<machine.lightsleep>` and
`machine.deepsleep([time_ms])<machine.deepsleep>` functions can be used to put
the ESP32 and peripherals (including the WiFi and Bluetooth radios) to sleep.
This is useful in many applications to conserve battery power. However,
applications must disable the WLAN peripheral (using
`active(False)<network.WLAN.active>`) before entering light or deep sleep (see
`Sleep Modes <https://docs.espressif.com/
projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html>`_).
Otherwise the WiFi radio may not be initialised properly after wake from
sleep. If the ``STA_IF`` and ``AP_IF`` interfaces have both been set
`active(True)<network.WLAN.active()>` then both interfaces should be set
`active(False)<network.WLAN.active()>` before entering any sleep mode.
**Example:** deep sleep::
import network, machine, espnow
sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected
peer = b'0\xaa\xaa\xaa\xaa\xaa' # MAC address of peer
e = espnow.ESPNow()
e.active(True)
e.add_peer(peer) # Register peer on STA_IF
print('Sending ping...')
if not e.send(peer, b'ping'):
print('Ping failed!')
e.active(False)
sta.active(False) # Disable the wifi before sleep
print('Going to sleep...')
machine.deepsleep(10000) # Sleep for 10 seconds then reboot
**Example:** light sleep::
import network, machine, espnow
sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected
sta.config(channel=6)
peer = b'0\xaa\xaa\xaa\xaa\xaa' # MAC address of peer
e = espnow.ESPNow()
e.active(True)
e.add_peer(peer) # Register peer on STA_IF
while True:
print('Sending ping...')
if not e.send(peer, b'ping'):
print('Ping failed!')
sta.active(False) # Disable the wifi before sleep
print('Going to sleep...')
machine.lightsleep(10000) # Sleep for 10 seconds
sta.active(True)
sta.config(channel=6) # Wifi loses config after lightsleep()

View File

@ -133,7 +133,9 @@ Other methods
Draw another FrameBuffer on top of the current one at the given coordinates.
If *key* is specified then it should be a color integer and the
corresponding color will be considered transparent: all pixels with that
color value will not be drawn.
color value will not be drawn. (If the *palette* is specified then the *key*
is compared to the value from *palette*, not to the value directly from
*fbuf*.)
The *palette* argument enables blitting between FrameBuffers with differing
formats. Typical usage is to render a monochrome or grayscale glyph/icon to

View File

@ -24,7 +24,7 @@ Functions
.. function:: mem_alloc()
Return the number of bytes of heap RAM that are allocated.
Return the number of bytes of heap RAM that are allocated by Python code.
.. admonition:: Difference to CPython
:class: attention
@ -33,8 +33,8 @@ Functions
.. function:: mem_free()
Return the number of bytes of available heap RAM, or -1 if this amount
is not known.
Return the number of bytes of heap RAM that is available for Python
code to allocate, or -1 if this amount is not known.
.. admonition:: Difference to CPython
:class: attention

106
docs/library/gzip.rst Normal file
View File

@ -0,0 +1,106 @@
:mod:`gzip` -- gzip compression & decompression
===============================================
.. module:: gzip
:synopsis: gzip compression & decompression
|see_cpython_module| :mod:`python:gzip`.
This module allows compression and decompression of binary data with the
`DEFLATE algorithm <https://en.wikipedia.org/wiki/DEFLATE>`_ used by the gzip
file format.
.. note:: Prefer to use :class:`deflate.DeflateIO` instead of the functions in this
module as it provides a streaming interface to compression and decompression
which is convenient and more memory efficient when working with reading or
writing compressed data to a file, socket, or stream.
**Availability:**
* This module is **not present by default** in official MicroPython firmware
releases as it duplicates functionality available in the :mod:`deflate
<deflate>` module.
* A copy of this module can be installed (or frozen)
from :term:`micropython-lib` (`source <https://github.com/micropython/micropython-lib/blob/master/python-stdlib/gzip/gzip.py>`_).
See :ref:`packages` for more information. This documentation describes that module.
* Compression support will only be available if compression support is enabled
in the built-in :mod:`deflate <deflate>` module.
Functions
---------
.. function:: open(filename, mode, /)
Wrapper around built-in :func:`open` returning a GzipFile instance.
.. function:: decompress(data, /)
Decompresses *data* into a bytes object.
.. function:: compress(data, /)
Compresses *data* into a bytes object.
Classes
-------
.. class:: GzipFile(*, fileobj, mode)
This class can be used to wrap a *fileobj* which is any
:term:`stream-like <stream>` object such as a file, socket, or stream
(including :class:`io.BytesIO`). It is itself a stream and implements the
standard read/readinto/write/close methods.
When the *mode* argument is ``"rb"``, reads from the GzipFile instance will
decompress the data in the underlying stream and return decompressed data.
If compression support is enabled then the *mode* argument can be set to
``"wb"``, and writes to the GzipFile instance will be compressed and written
to the underlying stream.
By default the GzipFile class will read and write data using the gzip file
format, including a header and footer with checksum and a window size of 512
bytes.
The **file**, **compresslevel**, and **mtime** arguments are not
supported. **fileobj** and **mode** must always be specified as keyword
arguments.
Examples
--------
A typical use case for :class:`gzip.GzipFile` is to read or write a compressed
file from storage:
.. code:: python
import gzip
# Reading:
with open("data.gz", "rb") as f:
with gzip.GzipFile(fileobj=f, mode="rb") as g:
# Use g.read(), g.readinto(), etc.
# Same, but using gzip.open:
with gzip.open("data.gz", "rb") as f:
# Use f.read(), f.readinto(), etc.
# Writing:
with open("data.gz", "wb") as f:
with gzip.GzipFile(fileobj=f, mode="wb") as g:
# Use g.write(...) etc
# Same, but using gzip.open:
with gzip.open("data.gz", "wb") as f:
# Use f.write(...) etc
# Write a dictionary as JSON in gzip format, with a
# small (64 byte) window size.
config = { ... }
with gzip.open("config.gz", "wb") as f:
json.dump(config, f)
For guidance on working with gzip sources and choosing the window size see the
note at the :ref:`end of the deflate documentation <deflate_wbits>`.

View File

@ -8,15 +8,17 @@ MicroPython libraries
Important summary of this section
* MicroPython provides built-in modules that mirror the functionality of the
Python standard library (e.g. :mod:`os`, :mod:`time`), as well as
MicroPython-specific modules (e.g. :mod:`bluetooth`, :mod:`machine`).
* Most standard library modules implement a subset of the functionality of
the equivalent Python module, and in a few cases provide some
MicroPython-specific extensions (e.g. :mod:`array`, :mod:`os`)
:ref:`Python standard library <micropython_lib_python>` (e.g. :mod:`os`,
:mod:`time`), as well as :ref:`MicroPython-specific modules <micropython_lib_micropython>`
(e.g. :mod:`bluetooth`, :mod:`machine`).
* Most Python standard library modules implement a subset of the
functionality of the equivalent Python module, and in a few cases provide
some MicroPython-specific extensions (e.g. :mod:`array`, :mod:`os`)
* Due to resource constraints or other limitations, some ports or firmware
versions may not include all the functionality documented here.
* To allow for extensibility, the built-in modules can be extended from
Python code loaded onto the device.
* To allow for extensibility, some built-in modules can be
:ref:`extended from Python code <micropython_lib_extending>` loaded onto
the device filesystem.
This chapter describes modules (function and class libraries) which are built
into MicroPython. This documentation in general aspires to describe all modules
@ -41,6 +43,8 @@ Beyond the built-in libraries described in this documentation, many more
modules from the Python standard library, as well as further MicroPython
extensions to it, can be found in :term:`micropython-lib`.
.. _micropython_lib_python:
Python standard libraries and micro-libraries
---------------------------------------------
@ -53,18 +57,21 @@ library.
:maxdepth: 1
array.rst
asyncio.rst
binascii.rst
builtins.rst
cmath.rst
collections.rst
errno.rst
gc.rst
gzip.rst
hashlib.rst
heapq.rst
io.rst
json.rst
math.rst
os.rst
platform.rst
random.rst
re.rst
select.rst
@ -73,10 +80,10 @@ library.
struct.rst
sys.rst
time.rst
uasyncio.rst
zlib.rst
_thread.rst
.. _micropython_lib_micropython:
MicroPython-specific libraries
------------------------------
@ -90,6 +97,7 @@ the following libraries.
bluetooth.rst
btree.rst
cryptolib.rst
deflate.rst
framebuf.rst
machine.rst
micropython.rst
@ -155,6 +163,11 @@ The following libraries are specific to the ESP8266 and ESP32.
esp.rst
esp32.rst
.. toctree::
:maxdepth: 1
espnow.rst
Libraries specific to the RP2040
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -176,23 +189,60 @@ The following libraries are specific to the Zephyr port.
zephyr.rst
.. _micropython_lib_extending:
Extending built-in libraries from Python
----------------------------------------
In most cases, the above modules are actually named ``umodule`` rather than
``module``, but MicroPython will alias any module prefixed with a ``u`` to the
non-``u`` version. However a file (or :term:`frozen module`) named
``module.py`` will take precedence over this alias.
A subset of the built-in modules are able to be extended by Python code by
providing a module of the same name in the filesystem. This extensibility
applies to the following Python standard library modules which are built-in to
the firmware: ``array``, ``binascii``, ``collections``, ``errno``, ``gzip``,
``hashlib``, ``heapq``, ``io``, ``json``, ``os``, ``platform``, ``random``,
``re``, ``select``, ``socket``, ``ssl``, ``struct``, ``time`` ``zlib``, as well
as the MicroPython-specific ``machine`` module. All other built-in modules
cannot be extended from the filesystem.
This allows the user to provide an extended implementation of a built-in library
(perhaps to provide additional CPython compatibility). The user-provided module
(in ``module.py``) can still use the built-in functionality by importing
``umodule`` directly. This is used extensively in :term:`micropython-lib`. See
:ref:`packages` for more information.
(perhaps to provide additional CPython compatibility or missing functionality).
This is used extensively in :term:`micropython-lib`, see :ref:`packages` for
more information. The filesystem module will typically do a wildcard import of
the built-in module in order to inherit all the globals (classes, functions and
variables) from the built-in.
This applies to both the Python standard libraries (e.g. ``os``, ``time``, etc),
but also the MicroPython libraries too (e.g. ``machine``, ``bluetooth``, etc).
The main exception is the port-specific libraries (``pyb``, ``esp``, etc).
In MicroPython v1.21.0 and higher, to prevent the filesystem module from
importing itself, it can force an import of the built-in module it by
temporarily clearing ``sys.path`` during the import. For example, to extend the
``time`` module from Python, a file named ``time.py`` on the filesystem would
do the following::
*Other than when you specifically want to force the use of the built-in module,
we recommend always using* ``import module`` *rather than* ``import umodule``.
_path = sys.path
sys.path = ()
try:
from time import *
finally:
sys.path = _path
del _path
def extra_method():
pass
The result is that ``time.py`` contains all the globals of the built-in ``time``
module, but adds ``extra_method``.
In earlier versions of MicroPython, you can force an import of a built-in module
by appending a ``u`` to the start of its name. For example, ``import utime``
instead of ``import time``. For example, ``time.py`` on the filesystem could
look like::
from utime import *
def extra_method():
pass
This way is still supported, but the ``sys.path`` method described above is now
preferred as the ``u``-prefix will be removed from the names of built-in
modules in a future version of MicroPython.
*Other than when it specifically needs to force the use of the built-in module,
code should always use* ``import module`` *rather than* ``import umodule``.

View File

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

View File

@ -4,7 +4,7 @@
class ADC -- analog to digital conversion
=========================================
The ADC class provides an interface to analog-to-digital convertors, and
The ADC class provides an interface to analog-to-digital converters, and
represents a single endpoint that can sample a continuous voltage and
convert it to a discretised value.

View File

@ -39,9 +39,9 @@ Methods
Configure the ADC peripheral. *bits* will set the resolution of the
conversion process.
.. method:: ADCBlock.connect(channel)
ADCBlock.connect(source)
ADCBlock.connect(channel, source)
.. method:: ADCBlock.connect(channel, *, ...)
ADCBlock.connect(source, *, ...)
ADCBlock.connect(channel, source, *, ...)
Connect up a channel on the ADC peripheral so it is ready for sampling,
and return an :ref:`ADC <machine.ADC>` object that represents that connection.
@ -56,3 +56,6 @@ Methods
If both *channel* and *source* are given then they are connected together
and made ready for sampling.
Any additional keyword arguments are used to configure the returned ADC object,
via its :meth:`init <machine.ADC.init>` method.

View File

@ -52,7 +52,7 @@ Example usage::
Constructors
------------
.. class:: I2C(id, *, scl, sda, freq=400000)
.. class:: I2C(id, *, scl, sda, freq=400000, timeout=50000)
Construct and return a new I2C object using the following parameters:
@ -62,6 +62,8 @@ Constructors
- *sda* should be a pin object specifying the pin to use for SDA.
- *freq* should be an integer which sets the maximum frequency
for SCL.
- *timeout* is the maximum time in microseconds to allow for I2C
transactions. This parameter is not allowed on some ports.
Note that some ports/boards will have default values of *scl* and *sda*
that can be changed in this constructor. Others will have fixed values
@ -91,6 +93,10 @@ General Methods
- *sda* is a pin object for the SDA line
- *freq* is the SCL clock rate
In the case of hardware I2C the actual clock frequency may be lower than the
requested frequency. This is dependent on the platform hardware. The actual
rate may be determined by printing the I2C object.
.. method:: I2C.deinit()
Turn off the I2C bus.

View File

@ -47,7 +47,7 @@ I2S objects can be created and initialized using::
3 modes of operation are supported:
- blocking
- non-blocking
- uasyncio
- asyncio
blocking::
@ -63,13 +63,13 @@ non-blocking::
audio_in.irq(i2s_callback) # i2s_callback is called when buf is filled
num_read = audio_in.readinto(buf) # returns immediately
uasyncio::
asyncio::
swriter = uasyncio.StreamWriter(audio_out)
swriter = asyncio.StreamWriter(audio_out)
swriter.write(buf)
await swriter.drain()
sreader = uasyncio.StreamReader(audio_in)
sreader = asyncio.StreamReader(audio_in)
num_read = await sreader.readinto(buf)
Some codec devices like the WM8960 or SGTL5000 require separate initialization
@ -103,7 +103,7 @@ Constructor
- ``ibuf`` specifies internal buffer length (bytes)
For all ports, DMA runs continuously in the background and allows user applications to perform other operations while
sample data is transfered between the internal buffer and the I2S peripheral unit.
sample data is transferred between the internal buffer and the I2S peripheral unit.
Increasing the size of the internal buffer has the potential to increase the time that user applications can perform non-I2S operations
before underflow (e.g. ``write`` method) or overflow (e.g. ``readinto`` method).

View File

@ -10,7 +10,8 @@ Example usage::
from machine import PWM
pwm = PWM(pin) # create a PWM object on a pin
pwm = PWM(pin, freq=50, duty_u16=8192) # create a PWM object on a pin
# and set freq and duty
pwm.duty_u16(32768) # set duty to 50%
# reinitialise with a period of 200us, duty of 5us
@ -23,7 +24,7 @@ Example usage::
Constructors
------------
.. class:: PWM(dest, *, freq, duty_u16, duty_ns)
.. class:: PWM(dest, *, freq, duty_u16, duty_ns, invert)
Construct and return a new PWM object using the following parameters:
@ -34,10 +35,12 @@ Constructors
PWM cycle.
- *duty_u16* sets the duty cycle as a ratio ``duty_u16 / 65535``.
- *duty_ns* sets the pulse width in nanoseconds.
- *invert* inverts the respective output if the value is True
Setting *freq* may affect other PWM objects if the objects share the same
underlying PWM generator (this is hardware specific).
Only one of *duty_u16* and *duty_ns* should be specified at a time.
*invert* is not available at all ports.
Methods
-------

View File

@ -98,7 +98,7 @@ Methods
specify them as a tuple of ``pins`` parameter.
In the case of hardware SPI the actual clock frequency may be lower than the
requested baudrate. This is dependant on the platform hardware. The actual
requested baudrate. This is dependent on the platform hardware. The actual
rate may be determined by printing the SPI object.
.. method:: SPI.deinit()

View File

@ -38,13 +38,16 @@ Constructors
Methods
-------
.. method:: Timer.init(*, mode=Timer.PERIODIC, period=-1, callback=None)
.. method:: Timer.init(*, mode=Timer.PERIODIC, freq=-1, period=-1, callback=None)
Initialise the timer. Example::
def mycallback(t):
pass
# periodic at 1kHz
tim.init(mode=Timer.PERIODIC, freq=1000, callback=mycallback)
# periodic with 100ms period
tim.init(period=100, callback=mycallback)
@ -60,12 +63,17 @@ Methods
- ``Timer.PERIODIC`` - The timer runs periodically at the configured
frequency of the channel.
- ``freq`` - The timer frequency, in units of Hz. The upper bound of
the frequency is dependent on the port. When both the ``freq`` and
``period`` arguments are given, ``freq`` has a higher priority and
``period`` is ignored.
- ``period`` - The timer period, in milliseconds.
- ``callback`` - The callable to call upon expiration of the timer period.
The callback must take one argument, which is passed the Timer object.
The ``callback`` argument shall be specified. Otherwise an exception
will occurr upon timer expiration:
will occur upon timer expiration:
``TypeError: 'NoneType' object isn't callable``
.. method:: Timer.deinit()

View File

@ -188,7 +188,7 @@ Methods
For the rp2, esp8266 and nrf ports the call returns while the last byte is sent.
If required, a one character wait time has to be added in the calling script.
Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports
Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra
.. method:: UART.txdone()
@ -201,7 +201,7 @@ Methods
of a transfer is still being sent. If required, a one character wait time has to be
added in the calling script.
Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports
Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra
Constants
---------

View File

@ -25,9 +25,8 @@ Constructors
Create a WDT object and start it. The timeout must be given in milliseconds.
Once it is running the timeout cannot be changed and the WDT cannot be stopped either.
Notes: On the esp32 the minimum timeout is 1 second. On the esp8266 a timeout
cannot be specified, it is determined by the underlying system. On rp2040 devices,
the maximum timeout is 8388 ms.
Notes: On the esp8266 a timeout cannot be specified, it is determined by the underlying system.
On rp2040 devices, the maximum timeout is 8388 ms.
Methods
-------

View File

@ -19,6 +19,44 @@ This is true for both physical devices with IDs >= 0 and "virtual" devices
with negative IDs like -1 (these "virtual" devices are still thin shims on
top of real hardware and real hardware interrupts). See :ref:`isr_rules`.
Memory access
-------------
The module exposes three objects used for raw memory access.
.. data:: mem8
Read/write 8 bits of memory.
.. data:: mem16
Read/write 16 bits of memory.
.. data:: mem32
Read/write 32 bits of memory.
Use subscript notation ``[...]`` to index these objects with the address of
interest. Note that the address is the byte address, regardless of the size of
memory being accessed.
Example use (registers are specific to an stm32 microcontroller):
.. code-block:: python3
import machine
from micropython import const
GPIOA = const(0x48000000)
GPIO_BSRR = const(0x18)
GPIO_IDR = const(0x10)
# set PA2 high
machine.mem32[GPIOA + GPIO_BSRR] = 1 << 2
# read PA3
value = (machine.mem32[GPIOA + GPIO_IDR] >> 3) & 1
Reset related functions
-----------------------

View File

@ -7,9 +7,9 @@
This module provides a driver for WS2818 / NeoPixel LEDs.
.. note:: This module is only included by default on the ESP8266, ESP32 and RP2
ports. On STM32 / Pyboard, you can `download the module
<https://github.com/micropython/micropython/blob/master/drivers/neopixel/neopixel.py>`_
and copy it to the filesystem.
ports. On STM32 / Pyboard and others, you can either install the
``neopixel`` package using :term:`mip`, or you can download the module
directly from :term:`micropython-lib` and copy it to the filesystem.
class NeoPixel
--------------

View File

@ -19,7 +19,7 @@ Example usage::
Constructors
------------
.. class:: LAN(id, *, phy_type=<board_default>, phy_addr=<board_default>, phy_clock=<board_default>)
.. class:: LAN(id, *, phy_type=<board_default>, phy_addr=<board_default>, ref_clk_mode=<board_default>)
Create a LAN driver object, initialise the LAN module using the given
PHY driver name, and return the LAN object.
@ -31,13 +31,15 @@ Constructors
is the default. Suitable values are port specific.
- *phy_addr* specifies the address of the PHY interface. As with *phy_type*, the hardwired value has
to be used for most boards and that value is the default.
- *phy_clock* specifies, whether the data clock is provided by the Ethernet controller or the PYH interface.
The default value is the one that matches the board. If set to ``True``, the clock is driven by the
Ethernet controller, otherwise by the PHY interface.
- *ref_clk_mode* specifies, whether the data clock is provided by the Ethernet controller or
the PYH interface.
The default value is the one that matches the board. If set to ``LAN.OUT`` or ``Pin.OUT``
or ``True``, the clock is driven by the Ethernet controller, if set to ``LAN.IN``
or ``Pin.IN`` or ``False``, the clock is driven by the PHY interface.
For example, with the Seeed Arch Mix board you can use::
nic = LAN(0, phy_type=LAN.PHY_LAN8720, phy_addr=2, phy_clock=False)
nic = LAN(0, phy_type=LAN.PHY_LAN8720, phy_addr=1, ref_clk_mode=Pin.IN)
Methods
-------

View File

@ -130,7 +130,23 @@ Methods
hidden Whether SSID is hidden (boolean)
security Security protocol supported (enumeration, see module constants)
key Access key (string)
hostname The hostname that will be sent to DHCP (STA interfaces) and mDNS (if supported, both STA and AP)
hostname The hostname that will be sent to DHCP (STA interfaces) and mDNS (if supported, both STA and AP). (Deprecated, use :func:`network.hostname` instead)
reconnects Number of reconnect attempts to make (integer, 0=none, -1=unlimited)
txpower Maximum transmit power in dBm (integer or float)
pm WiFi Power Management setting (see below for allowed values)
============= ===========
Constants
---------
.. data:: WLAN.PM_PERFORMANCE
WLAN.PM_POWERSAVE
WLAN.PM_NONE
Allowed values for the ``WLAN.config(pm=...)`` network interface parameter:
* ``PM_PERFORMANCE``: enable WiFi power management to balance power
savings and WiFi performance
* ``PM_POWERSAVE``: enable WiFi power management with additional power
savings and reduced WiFi performance
* ``PM_NONE``: disable wifi power management

View File

@ -158,12 +158,50 @@ Network functions
The following are functions available in the network module.
.. function:: country([code])
Get or set the two-letter ISO 3166-1 Alpha-2 country code to be used for
radio compliance.
If the *code* parameter is provided, the country will be set to this value.
If the function is called without parameters, it returns the current
country.
The default code ``"XX"`` represents the "worldwide" region.
.. function:: hostname([name])
Get or set the hostname that will identify this device on the network. It will
be used by all interfaces.
This hostname is used for:
* Sending to the DHCP server in the client request. (If using DHCP)
* Broadcasting via mDNS. (If enabled)
If the *name* parameter is provided, the hostname will be set to this value.
If the function is called without parameters, it returns the current
hostname.
A change in hostname is typically only applied during connection. For DHCP
this is because the hostname is part of the DHCP client request, and the
implementation of mDNS in most ports only initialises the hostname once
during connection. For this reason, you must set the hostname before
activating/connecting your network interfaces.
The length of the hostname is limited to 32 characters.
:term:`MicroPython ports <MicroPython port>` may choose to set a lower
limit for memory reasons. If the given name does not fit, a `ValueError`
is raised.
The default hostname is typically the name of the board.
.. function:: phy_mode([mode])
Get or set the PHY mode.
If the *mode* parameter is provided, sets the mode to its value. If
the function is called without parameters, returns the current mode.
If the *mode* parameter is provided, the PHY mode will be set to this value.
If the function is called without parameters, it returns the current PHY
mode.
The possible modes are defined as constants:
* ``MODE_11B`` -- IEEE 802.11b,

View File

@ -86,7 +86,7 @@ Filesystem access
.. function:: statvfs(path)
Get the status of a fileystem.
Get the status of a filesystem.
Returns a tuple with the filesystem information in the following order:

38
docs/library/platform.rst Normal file
View File

@ -0,0 +1,38 @@
:mod:`platform` -- access to underlying platforms identifying data
===================================================================
.. module:: platform
:synopsis: access to underlying platforms identifying data
|see_cpython_module| :mod:`python:platform`.
This module tries to retrieve as much platform-identifying data as possible. It
makes this information available via function APIs.
Functions
---------
.. function:: platform()
Returns a string identifying the underlying platform. This string is composed
of several substrings in the following order, delimited by dashes (``-``):
- the name of the platform system (e.g. Unix, Windows or MicroPython)
- the MicroPython version
- the architecture of the platform
- the version of the underlying platform
- the concatenation of the name of the libc that MicroPython is linked to
and its corresponding version.
For example, this could be
``"MicroPython-1.20.0-xtensa-IDFv4.2.4-with-newlib3.0.0"``.
.. function:: python_compiler()
Returns a string identifying the compiler used for compiling MicroPython.
.. function:: libc_ver()
Returns a tuple of strings *(lib, version)*, where *lib* is the name of the
libc that MicroPython is linked to, and *version* the corresponding version
of this libc.

View File

@ -252,7 +252,7 @@ Methods
For example::
buf = bytearray(8)
lst = [0, 0, 0, memoryview(buf)]
lst = [0, 0, 0, 0, memoryview(buf)]
# No heap memory is allocated in the following call
can.recv(0, lst)
@ -272,7 +272,7 @@ Methods
- *fdf* for CAN FD controllers, if set to True, the frame will have an FD
frame format, which supports data payloads up to 64 bytes.
- *brs* for CAN FD controllers, if set to True, the bitrate switching mode
is enabled, in which the data phase is transmitted at a differet bitrate.
is enabled, in which the data phase is transmitted at a different bitrate.
See :meth:`CAN.init` for the data bit timing configuration parameters.
If timeout is 0 the message is placed in a buffer in one of three hardware

View File

@ -96,6 +96,10 @@ Methods
that DMA transfers have more precise timing but currently do not handle bus
errors properly)
The actual clock frequency may be lower than the requested frequency.
This is dependent on the platform hardware. The actual rate may be determined
by printing the I2C object.
.. method:: I2C.is_ready(addr)
Check if an I2C device responds to the given address. Only valid when in controller mode.

View File

@ -24,7 +24,7 @@ This module implements a pseudo-random number generator (PRNG).
.. note::
The :func:`randrange`, :func:`randint` and :func:`choice` functions are only
available if the ``MICROPY_PY_URANDOM_EXTRA_FUNCS`` configuration option is
available if the ``MICROPY_PY_RANDOM_EXTRA_FUNCS`` configuration option is
enabled.
@ -73,7 +73,7 @@ Other Functions
supported by the port) initialise the PRNG with a true random number
(usually a hardware generated random number).
The ``None`` case only works if ``MICROPY_PY_URANDOM_SEED_INIT_FUNC`` is
The ``None`` case only works if ``MICROPY_PY_RANDOM_SEED_INIT_FUNC`` is
enabled by the port, otherwise it raises ``ValueError``.
.. function:: choice(sequence)

View File

@ -82,11 +82,18 @@ Methods
.. method:: StateMachine.exec(instr)
Execute a single PIO instruction. Uses `asm_pio_encode` to encode the
instruction from the given string *instr*.
Execute a single PIO instruction.
If *instr* is a string then uses `asm_pio_encode` to encode the instruction
from the given string.
>>> sm.exec("set(0, 1)")
If *instr* is an integer then it is treated as an already encoded PIO
machine code instruction to be executed.
>>> sm.exec(rp2.asm_pio_encode("out(y, 8)", 0))
.. method:: StateMachine.get(buf=None, shift=0)
Pull a word from the state machine's RX FIFO.
@ -99,13 +106,17 @@ Methods
.. method:: StateMachine.put(value, shift=0)
Push a word onto the state machine's TX FIFO.
Push words onto the state machine's TX FIFO.
If the FIFO is full, it blocks until there is space (i.e. the state machine
pulls a word).
*value* can be an integer, an array of type ``B``, ``H`` or ``I``, or a
`bytearray`.
The value is first shifted left by *shift* bits, i.e. the state machine
receives ``value << shift``.
This method will block until all words have been written to the FIFO. If
the FIFO is, or becomes, full, the method will block until the state machine
pulls enough words to complete the write.
Each word is first shifted left by *shift* bits, i.e. the state machine
receives ``word << shift``.
.. method:: StateMachine.rx_fifo()

View File

@ -66,6 +66,17 @@ For running PIO programs, see :class:`rp2.StateMachine`.
>>> rp2.asm_pio_encode("set(0, 1)", 0)
57345
.. function:: bootsel_button()
Temporarily turns the QSPI_SS pin into an input and reads its value,
returning 1 for low and 0 for high.
On a typical RP2040 board with a BOOTSEL button, a return value of 1
indicates that the button is pressed.
Since this function temporarily disables access to the external flash
memory, it also temporarily disables interrupts and the other core to
prevent them from trying to execute code from flash.
.. class:: PIOASMError
This exception is raised from `asm_pio()` or `asm_pio_encode()` if there is

View File

@ -29,7 +29,7 @@ returned by `getaddrinfo` function, which must be used to resolve textual addres
# You must use getaddrinfo() even for numeric addresses
sockaddr = socket.getaddrinfo('127.0.0.1', 80)[0][-1]
# Now you can use that address
sock.connect(addr)
sock.connect(sockaddr)
Using `getaddrinfo` is the most efficient (both in terms of memory and processing
power) and portable way to work with addresses.

View File

@ -15,21 +15,11 @@ Functions
.. function:: ssl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, cadata=None, server_hostname=None, do_handshake=True)
Takes a `stream` *sock* (usually socket.socket instance of ``SOCK_STREAM`` type),
and returns an instance of ssl.SSLSocket, which wraps the underlying stream in
an SSL context. Returned object has the usual `stream` interface methods like
``read()``, ``write()``, etc.
A server-side SSL socket should be created from a normal socket returned from
:meth:`~socket.socket.accept()` on a non-SSL listening server socket.
- *do_handshake* determines whether the handshake is done as part of the ``wrap_socket``
or whether it is deferred to be done as part of the initial reads or writes
(there is no ``do_handshake`` method as in CPython).
For blocking sockets doing the handshake immediately is standard. For non-blocking
sockets (i.e. when the *sock* passed into ``wrap_socket`` is in non-blocking mode)
the handshake should generally be deferred because otherwise ``wrap_socket`` blocks
until it completes. Note that in AXTLS the handshake can be deferred until the first
read or write but it then blocks until completion.
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`
method on that context object. The arguments *sock*, *server_side* and *server_hostname* are
passed through unchanged to the method call. The argument *do_handshake* is passed through as
*do_handshake_on_connect*. The remaining arguments have the following behaviour:
- *cert_reqs* determines whether the peer (server or client) must present a valid certificate.
Note that for mbedtls based ports, ``ssl.CERT_NONE`` and ``ssl.CERT_OPTIONAL`` will not
@ -38,13 +28,67 @@ Functions
- *cadata* is a bytes object containing the CA certificate chain (in DER format) that will
validate the peer's certificate. Currently only a single DER-encoded certificate is supported.
Depending on the underlying module implementation in a particular
:term:`MicroPython port`, some or all keyword arguments above may be not supported.
class SSLContext
----------------
.. class:: SSLContext(protocol, /)
Create a new SSLContext instance. The *protocol* argument must be one of the ``PROTOCOL_*``
constants.
.. method:: SSLContext.load_cert_chain(certfile, keyfile)
Load a private key and the corresponding certificate. The *certfile* is a string
with the file path of the certificate. The *keyfile* is a string with the file path
of the private key.
.. admonition:: Difference to CPython
:class: attention
MicroPython extension: *certfile* and *keyfile* can be bytes objects instead of
strings, in which case they are interpreted as the actual certificate/key data.
.. method:: SSLContext.load_verify_locations(cafile=None, cadata=None)
Load the CA certificate chain that will validate the peer's certificate.
*cafile* is the file path of the CA certificates. *cadata* is a bytes object
containing the CA certificates. Only one of these arguments should be provided.
.. method:: SSLContext.get_ciphers()
Get a list of enabled ciphers, returned as a list of strings.
.. method:: SSLContext.set_ciphers(ciphers)
Set the available ciphers for sockets created with this context. *ciphers* should be
a list of strings in the `IANA cipher suite format <https://wiki.mozilla.org/Security/Cipher_Suites>`_ .
.. method:: SSLContext.wrap_socket(sock, *, server_side=False, do_handshake_on_connect=True, server_hostname=None)
Takes a `stream` *sock* (usually socket.socket instance of ``SOCK_STREAM`` type),
and returns an instance of ssl.SSLSocket, wrapping the underlying stream.
The returned object has the usual `stream` interface methods like
``read()``, ``write()``, etc.
- *server_side* selects whether the wrapped socket is on the server or client side.
A server-side SSL socket should be created from a normal socket returned from
:meth:`~socket.socket.accept()` on a non-SSL listening server socket.
- *do_handshake_on_connect* determines whether the handshake is done as part of the ``wrap_socket``
or whether it is deferred to be done as part of the initial reads or writes
For blocking sockets doing the handshake immediately is standard. For non-blocking
sockets (i.e. when the *sock* passed into ``wrap_socket`` is in non-blocking mode)
the handshake should generally be deferred because otherwise ``wrap_socket`` blocks
until it completes. Note that in AXTLS the handshake can be deferred until the first
read or write but it then blocks until completion.
- *server_hostname* is for use as a client, and sets the hostname to check against the received
server certificate. It also sets the name for Server Name Indication (SNI), allowing the server
to present the proper certificate.
Depending on the underlying module implementation in a particular
:term:`MicroPython port`, some or all keyword arguments above may be not supported.
.. warning::
Some implementations of ``ssl`` module do NOT validate server certificates,
@ -55,6 +99,17 @@ Functions
returns an object more similar to CPython's ``SSLObject`` which does not have
these socket methods.
.. attribute:: SSLContext.verify_mode
Set or get the behaviour for verification of peer certificates. Must be one of the
``CERT_*`` constants.
.. note::
``ssl.CERT_REQUIRED`` requires the device's date/time to be properly set, e.g. using
`mpremote rtc --set <mpremote_command_rtc>` or ``ntptime``, and ``server_hostname``
must be specified when on the client side.
Exceptions
----------
@ -65,8 +120,14 @@ Exceptions
Constants
---------
.. data:: ssl.PROTOCOL_TLS_CLIENT
ssl.PROTOCOL_TLS_SERVER
Supported values for the *protocol* parameter.
.. data:: ssl.CERT_NONE
ssl.CERT_OPTIONAL
ssl.CERT_REQUIRED
Supported values for *cert_reqs* parameter.
Supported values for *cert_reqs* parameter, and the :attr:`SSLContext.verify_mode`
attribute.

View File

@ -102,3 +102,39 @@ the second CPU, the RF core.
Execute a HCI command on the SYS channel. The execution is synchronous.
Returns a bytes object with the result of the SYS command.
Functions specific to STM32WLxx MCUs
------------------------------------
These functions are available on STM32WLxx microcontrollers, and interact with
the integrated "SUBGHZ" radio modem peripheral.
.. function:: subghz_cs(level)
Sets the internal SPI CS pin attached to the radio peripheral. The ``level``
argument is active-low: a truthy value means "CS pin high" and de-asserts the
signal, a falsey value means "CS pin low" and asserts the signal.
The internal-only SPI bus corresponding to this CS signal can be instantiated
using :ref:`machine.SPI()<machine.SPI>` ``id`` value ``"SUBGHZ"``.
.. function:: subghz_irq(handler)
Sets the internal SUBGHZ radio interrupt handler to the provided
function. The handler function is called as a "hard" interrupt in response to
radio peripheral interrupts. See :ref:`isr_rules` for more information about
interrupt handlers in MicroPython.
Calling this function with the handler argument set to None disables the IRQ.
Due to a hardware limitation, each time this IRQ fires MicroPython disables
it before calling the handler. In order to receive another interrupt, Python
code should call ``subghz_irq()`` to set the handler again. This has the side
effect of re-enabling the IRQ.
.. function:: subghz_is_busy()
Return a ``bool`` corresponding to the internal "RFBUSYS" signal from the
radio peripheral. Before sending a new command to the radio over SPI then
this function should be polled until it returns ``False``, to confirm the
busy signal is de-asserted.

View File

@ -6,11 +6,58 @@
|see_cpython_module| :mod:`python:struct`.
Supported size/byte order prefixes: ``@``, ``<``, ``>``, ``!``.
The following byte orders are supported:
Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``,
``L``, ``q``, ``Q``, ``s``, ``P``, ``f``, ``d`` (the latter 2 depending
on the floating-point support).
+-----------+------------------------+----------+-----------+
| Character | Byte order | Size | Alignment |
+===========+========================+==========+===========+
| @ | native | native | native |
+-----------+------------------------+----------+-----------+
| < | little-endian | standard | none |
+-----------+------------------------+----------+-----------+
| > | big-endian | standard | none |
+-----------+------------------------+----------+-----------+
| ! | network (= big-endian) | standard | none |
+-----------+------------------------+----------+-----------+
The following data types are supported:
+--------+--------------------+-------------------+---------------+
| Format | C Type | Python type | Standard size |
+========+====================+===================+===============+
| b | signed char | integer | 1 |
+--------+--------------------+-------------------+---------------+
| B | unsigned char | integer | 1 |
+--------+--------------------+-------------------+---------------+
| h | short | integer | 2 |
+--------+--------------------+-------------------+---------------+
| H | unsigned short | integer | 2 |
+--------+--------------------+-------------------+---------------+
| i | int | integer (`1<fn>`) | 4 |
+--------+--------------------+-------------------+---------------+
| I | unsigned int | integer (`1<fn>`) | 4 |
+--------+--------------------+-------------------+---------------+
| l | long | integer (`1<fn>`) | 4 |
+--------+--------------------+-------------------+---------------+
| L | unsigned long | integer (`1<fn>`) | 4 |
+--------+--------------------+-------------------+---------------+
| q | long long | integer (`1<fn>`) | 8 |
+--------+--------------------+-------------------+---------------+
| Q | unsigned long long | integer (`1<fn>`) | 8 |
+--------+--------------------+-------------------+---------------+
| f | float | float (`2<fn>`) | 4 |
+--------+--------------------+-------------------+---------------+
| d | double | float (`2<fn>`) | 8 |
+--------+--------------------+-------------------+---------------+
| s | char[] | bytes | |
+--------+--------------------+-------------------+---------------+
| P | void * | integer | |
+--------+--------------------+-------------------+---------------+
.. _fn:
(1) Requires long support when used with values larger than 30 bits.
(2) Requires floating point support.
.. admonition:: Difference to CPython
:class: attention
@ -43,5 +90,5 @@ Functions
.. function:: unpack_from(fmt, data, offset=0, /)
Unpack from the *data* starting at *offset* according to the format string
*fmt*. *offset* may be negative to count from the end of *buffer*. The return
*fmt*. *offset* may be negative to count from the end of *data*. The return
value is a tuple of the unpacked values.

View File

@ -46,7 +46,7 @@ Functions
.. function:: settrace(tracefunc)
Enable tracing of bytecode execution. For details see the `CPython
documentaion <https://docs.python.org/3/library/sys.html#sys.settrace>`_.
documentation <https://docs.python.org/3/library/sys.html#sys.settrace>`_.
This function requires a custom MicroPython build as it is typically not
present in pre-built firmware (due to it affecting performance). The relevant

View File

@ -163,8 +163,8 @@ Functions
However, values returned by `ticks_ms()`, etc. functions may wrap around, so
directly using subtraction on them will produce incorrect result. That is why
`ticks_diff()` is needed, it implements modular (or more specifically, ring)
arithmetics to produce correct result even for wrap-around values (as long as they not
too distant inbetween, see below). The function returns **signed** value in the range
arithmetic to produce correct result even for wrap-around values (as long as they not
too distant in between, see below). The function returns **signed** value in the range
[*-TICKS_PERIOD/2* .. *TICKS_PERIOD/2-1*] (that's a typical range definition for
two's-complement signed binary integers). If the result is negative, it means that
*ticks1* occurred earlier in time than *ticks2*. Otherwise, it means that
@ -183,7 +183,7 @@ Functions
has passed. To avoid this mistake, just look at the clock regularly. Your application
should do the same. "Too long sleep" metaphor also maps directly to application
behaviour: don't let your application run any single task for too long. Run tasks
in steps, and do time-keeping inbetween.
in steps, and do time-keeping in between.
`ticks_diff()` is designed to accommodate various usage patterns, among them:

View File

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

View File

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

View File

@ -32,7 +32,7 @@ Functions
* *CPU utilization is only printed if runtime statistics are configured via the ``CONFIG_THREAD_RUNTIME_STATS`` kconfig*
This function can only be accessed if ``CONFIG_THREAD_ANALYZER`` is configured for the port in ``zephyr/prj.conf``.
For more infomation, see documentation for Zephyr `thread analyzer
For more information, see documentation for Zephyr `thread analyzer
<https://docs.zephyrproject.org/latest/guides/debug_tools/thread-analyzer.html#thread-analyzer>`_.
.. function:: shell_exec(cmd_in)

View File

@ -1,38 +1,82 @@
:mod:`zlib` -- zlib decompression
=================================
:mod:`zlib` -- zlib compression & decompression
===============================================
.. module:: zlib
:synopsis: zlib decompression
:synopsis: zlib compression & decompression
|see_cpython_module| :mod:`python:zlib`.
This module allows to decompress binary data compressed with
This module allows compression and decompression of binary data with the
`DEFLATE algorithm <https://en.wikipedia.org/wiki/DEFLATE>`_
(commonly used in zlib library and gzip archiver). Compression
is not yet implemented.
(commonly used in the zlib library and gzip archiver).
.. note:: Prefer to use :class:`deflate.DeflateIO` instead of the functions in this
module as it provides a streaming interface to compression and decompression
which is convenient and more memory efficient when working with reading or
writing compressed data to a file, socket, or stream.
**Availability:**
* From MicroPython v1.21 onwards, this module may not be present by default on
all MicroPython firmware as it duplicates functionality available in
the :mod:`deflate <deflate>` module.
* A copy of this module can be installed (or frozen)
from :term:`micropython-lib` (`source <https://github.com/micropython/micropython-lib/blob/master/python-stdlib/zlib/zlib.py>`_).
See :ref:`packages` for more information. This documentation describes that module.
* Requires the built-in :mod:`deflate <deflate>` module (available since MicroPython v1.21)
* Compression support will only be available if compression support is enabled
in the built-in :mod:`deflate <deflate>` module.
Functions
---------
.. function:: decompress(data, wbits=0, bufsize=0, /)
.. function:: decompress(data, wbits=15, /)
Return decompressed *data* as bytes. *wbits* is DEFLATE dictionary window
size used during compression (8-15, the dictionary size is power of 2 of
that value). Additionally, if value is positive, *data* is assumed to be
zlib stream (with zlib header). Otherwise, if it's negative, it's assumed
to be raw DEFLATE stream. *bufsize* parameter is for compatibility with
CPython and is ignored.
Decompresses *data* into a bytes object.
.. class:: DecompIO(stream, wbits=0, /)
The *wbits* parameter works the same way as for :meth:`zlib.compress`
with the following additional valid values:
Create a `stream` wrapper which allows transparent decompression of
compressed data in another *stream*. This allows to process compressed
streams with data larger than available heap size. In addition to
values described in :func:`decompress`, *wbits* may take values
24..31 (16 + 8..15), meaning that input stream has gzip header.
* ``0``: Automatically determine the window size from the zlib header
(*data* must be in zlib format).
* ``35`` to ``47``: Auto-detect either the zlib or gzip format.
.. admonition:: Difference to CPython
:class: attention
As for :meth:`zlib.compress`, see the :mod:`CPython documentation for zlib <python:zlib>`
for more information about the *wbits* parameter. As for :meth:`zlib.compress`,
MicroPython also supports smaller window sizes than CPython. See more
:ref:`MicroPython-specific details <deflate_wbits>` in the
:mod:`deflate <deflate>` module documentation.
This class is MicroPython extension. It's included on provisional
basis and may be changed considerably or removed in later versions.
If the data to be decompressed requires a larger window size, it will
fail during decompression.
.. function:: compress(data, wbits=15, /)
Compresses *data* into a bytes object.
*wbits* allows you to configure the DEFLATE dictionary window size and the
output format. The window size allows you to trade-off memory usage for
compression level. A larger window size will allow the compressor to
reference fragments further back in the input. The output formats are "raw"
DEFLATE (no header/footer), zlib, and gzip, where the latter two
include a header and checksum.
The low four bits of the absolute value of *wbits* set the base-2 logarithm of
the DEFLATE dictionary window size. So for example, ``wbits=10``,
``wbits=-10``, and ``wbits=26`` all set the window size to 1024 bytes. Valid
window sizes are ``5`` to ``15`` inclusive (corresponding to 32 to 32k bytes).
Negative values of *wbits* between ``-5`` and ``-15`` correspond to "raw"
output mode, positive values between ``5`` and ``15`` correspond to zlib
output mode, and positive values between ``21`` and ``31`` correspond to
gzip output mode.
See the :mod:`CPython documentation for zlib <python:zlib>` for more
information about the *wbits* parameter. Note that MicroPython allows
for smaller window sizes, which is useful when memory is constrained while
still achieving a reasonable level of compression. It also speeds up
the compressor. See more :ref:`MicroPython-specific details <deflate_wbits>`
in the :mod:`deflate <deflate>` module documentation.

View File

@ -14,9 +14,9 @@ The pin assignment of UARTs to pins is fixed.
The UARTs are numbered 0..8. The rx/tx pins are assigned according to the
tables below:
================ =========== =========== =========== ===========
================= =========== =========== =========== ===========
Board / Pin UART0 UART1 UART2 UART3
================ =========== =========== =========== ===========
================= =========== =========== =========== ===========
Teensy 4.0 - 0/1 7/8 14/15
Teensy 4.1 - 0/1 7/8 14/15
MIMXRT1010-EVK Debug USB D0/D1 D7/D6 -
@ -27,9 +27,10 @@ MIMXRT1050-EVKB Debug USB D0/D1 D7/D6 D8/D9
MIMXRT1060-EVK Debug USB D0/D1 D7/D6 D8/D9
MIMXRT1064-EVK Debug USB D0/D1 D7/D6 D8/D9
MIMXRT1170-EVK Debug USB D0/D1 D12/D11 D10/D13
Olimex RT1010Py - RxD/TxD D5/D6 -
Seeed ARCH MIX - J3_19/J3_20 J4_16/J4_17 J4_06/J4_07
================ =========== =========== =========== ===========
Adafruit Metro M7 - D0/D1 D7/D3 A1/A0
Olimex RT1010Py - RxD/TxD D7/D8 D5/D6
Seeed ARCH MIX - J3_19/J3_20 J4_16/J4_17 J4_06/J4_07
================= =========== =========== =========== ===========
|
@ -61,38 +62,38 @@ PWM pin assignment
Pins are specified in the same way as for the Pin class. The following tables show
the assignment of the board Pins to PWM modules:
=========== ========== ========== ====== ============== ======
Pin/ MIMXRT 1010 1015 1020 1050/1060/1064 1170
=========== ========== ========== ====== ============== ======
D0 - Q1/1 F1/1/B - -
D1 - Q1/0 F1/1/A - -
D2 F1/3/B F1/3/A - F1/3/B -
D3 F1/3/A F1/0/A F2/3/B F4/0/A F1/2/A
D4 F1/3/A (*) Q1/2 Q2/1 F2/3/A Q4/2
D5 F1/0/B (*) F1/0/B F2/3/A F1/3/A F1/2/B
D6 - F1/2/B F2/0/A Q3/2 F1/0/A
D7 - - F1/0/A Q3/3 -
D8 F1/0/A F1/1/B F1/0/B F1/1/X Q4/3
D9 F1/1/B (*) F1/2/A F2/0/B F1/0/X F1/0/B
D10 F1/3/B - F2/2/B F1/0/B (*) F2/2/B
D11 F1/2/A - F2/1/A F1/1/A (*) -
D12 F1/2/B - F2/1/B F1/1/B (*) -
D13 F1/3/A - F2/2/A F1/0/A (*) F2/2/A
D14 F1/0/B - - F2/3/B -
D15 F1/0/A - - F2/3/A -
A0 - - F1/2/A - -
A1 F1/3/X F1/3/B F1/2/B - -
A2 F1/2/X F1/3/A F1/3/A - -
A3 - F1/2/A F1/3/B - -
A4 - - - Q3/1 -
A5 - - - Q3/0 -
D31 - - - - F1/2/B
D32 - - - - F1/2/A
D33 - - - - F1/1/B
D34 - - - - F1/1/A
D35 - - - - F1/0/B
D36 - - - - F1/0/A
=========== ========== ========== ====== ============== ======
=========== ========== ========== ====== ========== ====== ========
Pin/ MIMXRT 1010 1015 1020 1050/60/64 1170 Metro M7
=========== ========== ========== ====== ========== ====== ========
D0 - Q1/1 F1/1/B - - -
D1 - Q1/0 F1/1/A - - -
D2 F1/3/B F1/3/A - F1/3/B - -
D3 F1/3/A F1/0/A F2/3/B F4/0/A F1/2/A -
D4 F1/3/A (*) Q1/2 Q2/1 F2/3/A Q4/2 F1/0/B
D5 F1/0/B (*) F1/0/B F2/3/A F1/3/A F1/2/B F1/0/A
D6 - F1/2/B F2/0/A Q3/2 F1/0/A -
D7 - - F1/0/A Q3/3 - -
D8 F1/0/A F1/1/B F1/0/B F1/1/X Q4/3 F1/3/A
D9 F1/1/B (*) F1/2/A F2/0/B F1/0/X F1/0/B F1/3/B
D10 F1/3/B - F2/2/B F1/0/B (*) F2/2/B F1/2/A
D11 F1/2/A - F2/1/A F1/1/A (*) - F1/2/B
D12 F1/2/B - F2/1/B F1/1/B (*) - F1/1/A
D13 F1/3/A - F2/2/A F1/0/A (*) F2/2/A F1/1/B
D14 F1/0/B - - F2/3/B - F1/0/B
D15 F1/0/A - - F2/3/A - F1/0/A
A0 - - F1/2/A - - -
A1 F1/3/X F1/3/B F1/2/B - - -
A2 F1/2/X F1/3/A F1/3/A - - -
A3 - F1/2/A F1/3/B - - F1/3/B
A4 - - - Q3/1 - F1/2/X
A5 - - - Q3/0 - -
D31 - - - - F1/2/B -
D32 - - - - F1/2/A -
D33 - - - - F1/1/B -
D34 - - - - F1/1/A -
D35 - - - - F1/0/B -
D36 - - - - F1/0/A -
=========== ========== ========== ====== ========== ====== ========
Pins denoted with (*) are by default not wired at the board.
@ -318,6 +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 - -
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
================= ========================= ======================= ===============
@ -350,6 +352,7 @@ MIXMXRT1050-EVKB A4/A5 D1/D0 - - -
MIXMXRT1060-EVK A4/A5 D1/D0 - - -
MIXMXRT1064-EVK A4/A5 D1/D0 - - -
MIXMXRT1170-EVK D14/D15 D1/D0 A4/A5 D26/D25 D19/D18
Adafruit Metro M7 D14/D15 D0/D1
Olimex RT1010Py - SDA1/SCL1 SDA2/SCL2 - -
Seeed ARCH MIX J3_17/J3_16 J4_06/J4_07 J5_05/J5_04 - -
================= =========== =========== =========== ======= =======
@ -364,18 +367,19 @@ Hardware I2S pin assignment
Pin assignments for a few MIMXRT boards:
=============== == ===== ======== ======= ======= ======== ======= =======
Board ID MCK SCK_TX WS_TX SD_TX SCK_RX WS_RX SD_RX
=============== == ===== ======== ======= ======= ======== ======= =======
Teensy 4.0 1 23 26 27 7 21 20 8
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
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"
=============== == ===== ======== ======= ======= ======== ======= =======
================= == ===== ======== ======= ======= ======== ======= =======
Board ID MCK SCK_TX WS_TX SD_TX SCK_RX WS_RX SD_RX
================= == ===== ======== ======= ======= ======== ======= =======
Teensy 4.0 1 23 26 27 7 21 20 8
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
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"
================= == ===== ======== ======= ======= ======== ======= =======
Symbolic pin names are provided for the MIMXRT_10xx_DEV boards.
These are provided for the other boards as well.
These are provided for the other boards as well.

View File

@ -56,21 +56,18 @@ Use the :mod:`time <time>` module::
Timers
------
The i.MXRT port has three hardware timers. Use the :ref:`machine.Timer <machine.Timer>` class
with a timer ID from 0 to 2 (inclusive)::
The i.MXRT port supports virtual Timers. Example of usage::
from machine import Timer
tim0 = Timer(0)
tim0 = Timer(-1)
tim0.init(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(0))
tim1 = Timer(1)
tim1 = Timer(-1)
tim1.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(1))
The period is in milliseconds.
Virtual timers are not currently supported on this port.
.. _mimxrt_Pins_and_GPIO:
Pins and GPIO
@ -95,9 +92,7 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
Available Pins follow the ranges and labelling of the respective board, like:
- 0-33 for Teensy 4.0,
- 0-21 for the MIMXRT10xx-EVK board, or 'D0-Dxx', or 'A0-Ann',
- 0-14 for the Olimex RT1010Py board, or 'D0'-'Dxx' and 'A0'-'Ann'
- 'D0-Dxx', or 'A0-Ann' for Teensy 4.0, MIMXRT10xx-EVK ns Olimex board,
- 'J3_xx', 'J4_xx', 'J5_xx' for the Seeed ARCH MIX board,
or the pin names of the Pin.board or Pin.cpu classes.
@ -109,9 +104,9 @@ Notes:
* At the MIMXRT1010_EVK, pins D4, D5 and D9 of the Arduino connector are by
default not connected to the MCU. For details refer to the schematics.
* At the MIMXRT1170_EVK board, the inner rows of the Arduino connectors are assigned as follows:
- D16 - D23: J9, odd pin numbers; D17 is by default not connected.
- D24 - D27: J26, odd pin numbers; J63-J66 have to be closed to enable these pins.
- D29 - D36: J25, odd pin numbers; D29 and D30 are by default not connected.
- 'D16' - 'D23': J9, odd pin numbers; 'D17' is by default not connected.
- 'D24' - 'D27': J26, odd pin numbers; J63-J66 have to be closed to enable these pins.
- 'D29' - 'D36': J25, odd pin numbers; 'D29' and 'D30' are by default not connected.
There's a higher-level abstraction :ref:`machine.Signal <machine.Signal>`
which can be used to invert a pin. Useful for illuminating active-low LEDs
@ -148,22 +143,23 @@ handling signal groups. ::
from machine import Pin, PWM
pwm2 = PWM(Pin(2)) # create PWM object from a pin
pwm2.freq() # get current frequency
pwm2.freq(1000) # set frequency
pwm2.duty_u16() # get current duty cycle, range 0-65535
pwm2.duty_u16(200) # set duty cycle, range 0-65535
# create PWM object from a pin and set the frequency and duty cycle
pwm2 = PWM(Pin('D2'), freq=2000, duty_u16=32768)
pwm2.freq() # get the current frequency
pwm2.freq(1000) # set/change the frequency
pwm2.duty_u16() # get the current duty cycle, range 0-65535
pwm2.duty_u16(200) # set the duty cycle, range 0-65535
pwm2.deinit() # turn off PWM on the pin
# create a complementary signal pair on Pin 2 and 3
pwm2 = PWM((2, 3), freq=2000, duty_ns=20000)
pwm2 = PWM(('D2', 'D3'), freq=2000, duty_ns=20000)
# Create a group of four synchronized signals.
# Start with Pin(4) at submodule 0, which creates the sync pulse.
pwm4 = PWM(Pin(4), freq=1000, align=PWM.HEAD)
# Pins 5, 6, and 9 are pins at the same module
pwm5 = PWM(Pin(5), freq=1000, duty_u16=10000, align=PWM.HEAD, sync=True)
pwm6 = PWM(Pin(6), freq=1000, duty_u16=20000, align=PWM.HEAD, sync=True)
pwm9 = PWM(Pin(9), freq=1000, duty_u16=30000, align=PWM.HEAD, sync=True)
# Start with Pin('D4') at submodule 0, which creates the sync pulse.
pwm4 = PWM(Pin('D4'), freq=1000, align=PWM.HEAD)
# Pins D5, D6, and D9 are pins at the same module
pwm5 = PWM(Pin('D5'), freq=1000, duty_u16=10000, align=PWM.HEAD, sync=True)
pwm6 = PWM(Pin('D6', freq=1000, duty_u16=20000, align=PWM.HEAD, sync=True)
pwm9 = PWM(Pin('D9'), freq=1000, duty_u16=30000, align=PWM.HEAD, sync=True)
pwm3 # show the PWM objects properties
@ -209,8 +205,9 @@ PWM Constructor
- *align*\=value. Shortcuts for the pulse center setting, causing the pulse either at
the center of the frame (value=0), the leading edge at the begin (value=1) or the
trailing edge at the end of a pulse period (value=2).
- *invert*\=True|False channel_mask. Setting a bit in the mask inverts the respective channel.
Bit 0 inverts the first specified channel, bit 2 the second. The default is 0.
- *invert*\=value channel_mask. Setting a bit in the mask inverts the respective channel.
Bit 0 inverts the first specified channel, bit 1 the second. The default is 0. For a
PWM object with a single channel, True and False may be used as values.
- *sync*\=True|False. If a channel of a module's submodule 0 is already active, other
submodules of the same module can be forced to be synchronous to submodule 0. Their
pulse period start then at at same clock cycle. The default is False.
@ -257,7 +254,7 @@ Use the :ref:`machine.ADC <machine.ADC>` class::
from machine import ADC
adc = ADC(Pin(32)) # create ADC object on ADC pin
adc = ADC(Pin('A2')) # create ADC object on ADC pin
adc.read_u16() # read value, 0-65536 across voltage range 0.0v - 3.3v
The resolution of the ADC is 12 bit with 10 to 11 bit accuracy, irrespective of the
@ -275,7 +272,7 @@ Software SPI (using bit-banging) works on all pins, and is accessed via the
# construct a SoftSPI bus on the given pins
# polarity is the idle state of SCK
# phase=0 means sample on the first edge of SCK, phase=1 means the second
spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin('D0'), mosi=Pin('D2'), miso=Pin('D4'))
spi.init(baudrate=200000) # set the baudrate
@ -304,7 +301,7 @@ rates (up to 30Mhz). Hardware SPI is accessed via the
from machine import SPI, Pin
spi = SPI(0, 10000000)
cs_pin = Pin(6, Pin.OUT, value=1)
cs_pin = Pin('D6', Pin.OUT, value=1)
cs_pin(0)
spi.write('Hello World')
cs_pin(1)
@ -332,7 +329,7 @@ accessed via the :ref:`machine.SoftI2C <machine.SoftI2C>` class::
from machine import Pin, SoftI2C
i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=100000)
i2c = SoftI2C(scl=Pin('D5'), sda=Pin('D4'), freq=100000)
i2c.scan() # scan for devices
@ -366,7 +363,7 @@ See :ref:`machine.I2S <machine.I2S>`. Example using a Teensy 4.1 board with a si
external Codec like UDA1334.::
from machine import I2S, Pin
i2s = I2S(2, sck=Pin(26), ws=Pin(27), sd=Pin(7),
i2s = I2S(2, sck=Pin('D26'), ws=Pin('D27'), sd=Pin('D7'),
mode=I2S.TX, bts=16,format=I2S.STEREO,
rate=44100,ibuf=40000)
i2s.write(buf) # write buffer of audio samples to I2S device
@ -398,7 +395,7 @@ Example using the Teensy audio shield::
from machine import I2C, I2S, Pin
from sgtl5000 import CODEC
i2s = I2S(1, sck=Pin(21), ws=Pin(20), sd=Pin(7), mck=Pin(23),
i2s = I2S(1, sck=Pin('D21'), ws=Pin('D20'), sd=Pin('D7'), mck=Pin('D23'),
mode=I2S.TX, bits=16,rate=44100,format=I2S.STEREO,
ibuf=40000,
)
@ -476,7 +473,7 @@ The OneWire driver is implemented in software and works on all pins::
from machine import Pin
import onewire
ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12
ow = onewire.OneWire(Pin('D12')) # create a OneWire bus on GPIO12
ow.scan() # return a list of devices on the bus
ow.reset() # reset the bus
ow.readbyte() # read a byte
@ -506,12 +503,12 @@ The DHT driver is implemented in software and works on all pins::
import dht
import machine
d = dht.DHT11(machine.Pin(4))
d = dht.DHT11(machine.Pin('D4'))
d.measure()
d.temperature() # eg. 23 (°C)
d.humidity() # eg. 41 (% RH)
d = dht.DHT22(machine.Pin(4))
d = dht.DHT22(machine.Pin('D4'))
d.measure()
d.temperature() # eg. 23.6 (°C)
d.humidity() # eg. 41.3 (% RH)

View File

@ -120,7 +120,7 @@ minus sign in front of the y-coordinate in the ``hid.send()`` line above.
Restoring your pyboard to normal
--------------------------------
If you leave your pyboard as-is, it'll behave as a mouse everytime you plug
If you leave your pyboard as-is, it'll behave as a mouse every time you plug
it in. You probably want to change it back to normal. To do this you need
to first enter safe mode (see above), and then edit the ``boot.py`` file.
In the ``boot.py`` file, comment out (put a # in front of) the line with the

View File

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

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