Merge branch 'main' of origin into ESP32-S3-DevKitC-1-N32R8

This commit is contained in:
MicroDev 2022-11-18 09:40:20 +05:30
commit 3a418379d3
No known key found for this signature in database
GPG Key ID: 2C0867BE60967730
2112 changed files with 70699 additions and 32208 deletions

View File

@ -30,20 +30,20 @@ jobs:
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2.2.0
- uses: actions/checkout@v3
with:
submodules: false
fetch-depth: 1
- name: Set up Python 3
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: "3.x"
python-version: "3.10"
- name: Get CP deps
run: python tools/ci_fetch_deps.py test ${{ github.sha }}
- name: CircuitPython version
run: |
git describe --dirty --tags || git log --parents HEAD~4..
echo >>$GITHUB_ENV CP_VERSION=$(git describe --dirty --tags)
tools/describe || git log --parents HEAD~4..
echo >>$GITHUB_ENV CP_VERSION=$(tools/describe)
- name: Install dependencies
run: |
sudo apt-get update
@ -72,32 +72,45 @@ jobs:
run: MICROPY_CPYTHON3=python3.8 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests.py -j1 --emit native
working-directory: tests
- name: mpy Tests
run: MICROPY_CPYTHON3=python3.8 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests.py -j1 --mpy-cross-flags='-mcache-lookup-bc' --via-mpy -d basics float micropython
run: MICROPY_CPYTHON3=python3.8 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests.py -j1 --via-mpy -d basics float micropython
working-directory: tests
- name: Native mpy Tests
run: MICROPY_CPYTHON3=python3.8 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests.py -j1 --mpy-cross-flags='-mcache-lookup-bc' --via-mpy --emit native -d basics float micropython
run: MICROPY_CPYTHON3=python3.8 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests.py -j1 --via-mpy --emit native -d basics float micropython
working-directory: tests
- name: Build native modules
run: |
make -C examples/natmod/features1
make -C examples/natmod/features2
make -C examples/natmod/btree
make -C examples/natmod/framebuf
make -C examples/natmod/uheapq
make -C examples/natmod/urandom
make -C examples/natmod/ure
make -C examples/natmod/uzlib
- name: Test native modules
run: MICROPY_CPYTHON3=python3.8 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-natmodtests.py extmod/{btree*,framebuf*,uheapq*,ure*,uzlib*}.py
working-directory: tests
- name: Build mpy-cross.static-aarch64
run: make -C mpy-cross -j2 -f Makefile.static-aarch64
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: mpy-cross.static-aarch64
path: mpy-cross/mpy-cross.static-aarch64
- name: Build mpy-cross.static-raspbian
run: make -C mpy-cross -j2 -f Makefile.static-raspbian
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: mpy-cross.static-raspbian
path: mpy-cross/mpy-cross.static-raspbian
- name: Build mpy-cross.static
run: make -C mpy-cross -j2 -f Makefile.static
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: mpy-cross.static-amd64-linux
path: mpy-cross/mpy-cross.static
- name: Build mpy-cross.static-mingw
run: make -C mpy-cross -j2 -f Makefile.static-mingw
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: mpy-cross.static-x64-windows
path: mpy-cross/mpy-cross.static.exe
@ -112,44 +125,53 @@ jobs:
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross.static-raspbian s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross.static-raspbian-${{ env.CP_VERSION }} --no-progress --region us-east-1
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross.static s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross.static-amd64-linux-${{ env.CP_VERSION }} --no-progress --region us-east-1
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross.static.exe s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross.static-x64-windows-${{ env.CP_VERSION }}.exe --no-progress --region us-east-1
- name: "Get changes"
- name: Get last commit with checks
id: get-last-commit-with-checks
if: github.event_name == 'pull_request'
uses: dorny/paths-filter@v2
id: filter
working-directory: tools
env:
REPO: ${{ github.repository }}
PULL: ${{ github.event.number }}
GITHUB_TOKEN: ${{ github.token }}
EXCLUDE_COMMIT: ${{ github.event.after }}
run: python3 -u ci_changes_per_commit.py
- name: Get changes
id: get-changes
if: github.event_name == 'pull_request'
uses: tj-actions/changed-files@v34
with:
list-files: json
filters: |
changed:
- '**'
- name: "Set matrix"
json: "true"
base_sha: ${{ steps.get-last-commit-with-checks.outputs.commit }}
- name: Set matrix
id: set-matrix
working-directory: tools
env:
CHANGED_FILES: ${{ steps.filter.outputs.changed_files }}
CHANGED_FILES: ${{ toJSON(steps.get-changes.outputs.all_changed_and_modified_files) }}
LAST_FAILED_JOBS: ${{ steps.get-last-commit-with-checks.outputs.checkruns }}
run: python3 -u ci_set_matrix.py
mpy-cross-mac:
runs-on: macos-10.15
runs-on: macos-11
steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2.2.0
- uses: actions/checkout@v3
with:
submodules: false
fetch-depth: 1
- name: Set up Python 3
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: "3.x"
python-version: "3.10"
- name: Get CP deps
run: python tools/ci_fetch_deps.py mpy-cross-mac ${{ github.sha }}
- name: CircuitPython version
run: |
git describe --dirty --tags
echo >>$GITHUB_ENV CP_VERSION=$(git describe --dirty --tags)
tools/describe || git log --parents HEAD~4..
echo >>$GITHUB_ENV CP_VERSION=$(tools/describe)
- name: Install dependencies
run: |
brew install gettext
@ -161,29 +183,27 @@ jobs:
msgfmt --version
- name: Build mpy-cross
run: make -C mpy-cross -j2
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: mpy-cross-macos-catalina
name: mpy-cross-macos-11-x64
path: mpy-cross/mpy-cross
- name: Select SDK for M1 build
run: sudo xcode-select -switch /Applications/Xcode_12.3.app
- name: Build mpy-cross (arm64)
run: make -C mpy-cross -j2 -f Makefile.m1 V=2
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: mpy-cross-macos-bigsur-arm64
name: mpy-cross-macos-11-arm64
path: mpy-cross/mpy-cross-arm64
- name: Make universal binary
run: lipo -create -output mpy-cross-macos-universal mpy-cross/mpy-cross mpy-cross/mpy-cross-arm64
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: mpy-cross-macos-universal
name: mpy-cross-macos-11-universal
path: mpy-cross-macos-universal
- name: Upload mpy-cross build to S3
run: |
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross-macos-universal s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross-macos-universal-${{ env.CP_VERSION }} --no-progress --region us-east-1
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross-arm64 s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross-macos-bigsur-${{ env.CP_VERSION }}-arm64 --no-progress --region us-east-1
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross-macos-catalina-${{ env.CP_VERSION }} --no-progress --region us-east-1
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross-macos-universal s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross-macos-11-${{ env.CP_VERSION }}-universal --no-progress --region us-east-1
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross-arm64 s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross-macos-11-${{ env.CP_VERSION }}-arm64 --no-progress --region us-east-1
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross-macos-11-${{ env.CP_VERSION }}-x64 --no-progress --region us-east-1
env:
AWS_PAGER: ''
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
@ -196,7 +216,7 @@ jobs:
needs: test
if: ${{ needs.test.outputs.build-doc == 'True' }}
steps:
- uses: actions/checkout@v2.2.0
- uses: actions/checkout@v3
with:
submodules: false
fetch-depth: 1
@ -204,12 +224,12 @@ jobs:
run: python tools/ci_fetch_deps.py docs ${{ github.sha }}
- name: CircuitPython version
run: |
git describe --dirty --tags
echo >>$GITHUB_ENV CP_VERSION=$(git describe --dirty --tags)
tools/describe || git log --parents HEAD~4..
echo >>$GITHUB_ENV CP_VERSION=$(tools/describe)
- name: Set up Python 3
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: "3.x"
python-version: "3.10"
- name: Install dependencies
run: |
sudo apt-get update
@ -218,20 +238,20 @@ jobs:
pip install -r requirements-ci.txt -r requirements-doc.txt
- name: Build and Validate Stubs
run: make check-stubs -j2
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: stubs
path: circuitpython-stubs/dist/*
- name: Test Documentation Build (HTML)
run: sphinx-build -E -W -b html -D version=${{ env.CP_VERSION }} -D release=${{ env.CP_VERSION }} . _build/html
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: docs
path: _build/html
- name: Test Documentation Build (LaTeX/PDF)
run: |
make latexpdf
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: docs
path: _build/latex
@ -265,21 +285,22 @@ jobs:
if: ${{ needs.test.outputs.boards-arm != '[]' }}
steps:
- name: Set up Python 3
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: "3.x"
- uses: actions/checkout@v2.2.0
python-version: "3.10"
- uses: actions/checkout@v3
with:
submodules: false
fetch-depth: 1
- name: Get CP deps
run: python tools/ci_fetch_deps.py ${{ matrix.board }} ${{ github.sha }}
- uses: carlosperate/arm-none-eabi-gcc-action@v1
with:
release: '10-2020-q4'
- name: Install dependencies
run: |
sudo apt-get install -y gettext
pip install -r requirements-ci.txt -r requirements-dev.txt
wget --no-verbose https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
sudo tar -C /usr --strip-components=1 -xaf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
- name: Versions
run: |
gcc --version
@ -294,7 +315,7 @@ jobs:
working-directory: tools
env:
BOARDS: ${{ matrix.board }}
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: ${{ matrix.board }}
path: bin/${{ matrix.board }}
@ -317,10 +338,10 @@ jobs:
if: ${{ needs.test.outputs.boards-riscv != '[]' }}
steps:
- name: Set up Python 3
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: "3.x"
- uses: actions/checkout@v2.2.0
python-version: "3.10"
- uses: actions/checkout@v3
with:
submodules: false
fetch-depth: 1
@ -346,7 +367,7 @@ jobs:
working-directory: tools
env:
BOARDS: ${{ matrix.board }}
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: ${{ matrix.board }}
path: bin/${{ matrix.board }}
@ -369,23 +390,26 @@ jobs:
if: ${{ needs.test.outputs.boards-espressif != '[]' }}
steps:
- name: Set up Python 3
uses: actions/setup-python@v2
id: py3
uses: actions/setup-python@v4
with:
python-version: "3.x"
- uses: actions/checkout@v2.2.0
python-version: "3.10"
- uses: actions/checkout@v3
with:
submodules: false
fetch-depth: 1
- name: Get CP deps
run: python tools/ci_fetch_deps.py ${{ matrix.board }} ${{ github.sha }}
- name: CircuitPython version
run: git describe --dirty --tags
- uses: actions/cache@v2
run: |
tools/describe || git log --parents HEAD~4..
echo >>$GITHUB_ENV CP_VERSION=$(tools/describe)
- uses: actions/cache@v3
name: Fetch IDF tool cache
id: idf-cache
with:
path: ${{ github.workspace }}/.idf_tools
key: ${{ runner.os }}-idf-tools-${{ hashFiles('.git/modules/ports/espressif/esp-idf/HEAD') }}-20210923
key: ${{ runner.os }}-idf-tools-${{ hashFiles('.git/modules/ports/espressif/esp-idf/HEAD') }}-${{ steps.py3.outputs.python-path }}-20220404
- name: Clone IDF submodules
run: |
(cd $IDF_PATH && git submodule update --init)
@ -434,7 +458,7 @@ jobs:
IDF_PATH: ${{ github.workspace }}/ports/espressif/esp-idf
IDF_TOOLS_PATH: ${{ github.workspace }}/.idf_tools
BOARDS: ${{ matrix.board }}
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: ${{ matrix.board }}
path: bin/${{ matrix.board }}
@ -456,10 +480,10 @@ jobs:
if: ${{ needs.test.outputs.boards-aarch != '[]' }}
steps:
- name: Set up Python 3
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: "3.x"
- uses: actions/checkout@v2.2.0
python-version: "3.10"
- uses: actions/checkout@v3
with:
submodules: false
fetch-depth: 1
@ -471,8 +495,9 @@ jobs:
pip install -r requirements-ci.txt -r requirements-dev.txt
wget --no-verbose https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz
sudo tar -C /usr --strip-components=1 -xaf gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz
wget --no-verbose https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
sudo tar -C /usr --strip-components=1 -xaf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
- uses: carlosperate/arm-none-eabi-gcc-action@v1
with:
release: '10-2020-q4'
- name: Install mkfs.fat
run: |
wget https://github.com/dosfstools/dosfstools/releases/download/v4.2/dosfstools-4.2.tar.gz
@ -498,7 +523,7 @@ jobs:
working-directory: tools
env:
BOARDS: ${{ matrix.board }}
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: ${{ matrix.board }}
path: bin/${{ matrix.board }}

View File

@ -16,14 +16,14 @@ jobs:
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2.2.0
- uses: actions/checkout@v3
with:
submodules: false
fetch-depth: 1
- name: Set up Python 3
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: "3.x"
python-version: "3.10"
- name: Get CP deps
run: python tools/ci_fetch_deps.py website ${{ github.sha }}
- name: Install deps
@ -34,11 +34,13 @@ jobs:
gcc --version
python3 --version
- name: CircuitPython version
run: git describe --dirty --tags
run: |
tools/describe || git log --parents HEAD~4..
echo >>$GITHUB_ENV CP_VERSION=$(tools/describe)
- name: Website
run: python3 build_board_info.py
working-directory: tools
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
ADABOT_GITHUB_ACCESS_TOKEN: ${{ secrets.BLINKA_GITHUB_ACCESS_TOKEN }}
ADABOT_GITHUB_ACCESS_TOKEN: ${{ secrets.ADABOT_GITHUB_ACCESS_TOKEN }}
if: github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested')

View File

@ -5,12 +5,14 @@ on:
pull_request:
paths:
- '.github/workflows/*.yml'
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'lib/**'
- 'mpy-cross/**'
- 'ports/unix/**'
- 'ports/windows/**'
- 'py/**'
- 'requirements*.txt'
- 'tools/**'
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
@ -64,12 +66,12 @@ jobs:
pip install wheel
# requirements_dev.txt doesn't install on windows. (with msys2 python)
# instead, pick a subset for what we want to do
pip install cascadetoml jinja2 typer intelhex
pip install cascadetoml jinja2 typer click intelhex
# check that installed packages work....?
which python; python --version; python -c "import cascadetoml"
which python3; python3 --version; python3 -c "import cascadetoml"
- uses: actions/checkout@v2.2.0
- uses: actions/checkout@v3
with:
submodules: false
fetch-depth: 1
@ -77,8 +79,8 @@ jobs:
run: python tools/ci_fetch_deps.py windows ${{ github.sha }}
- name: CircuitPython version
run: |
git describe --dirty --tags
echo >>$GITHUB_ENV CP_VERSION=$(git describe --dirty --tags)
tools/describe || git log --parents HEAD~4..
echo >>$GITHUB_ENV CP_VERSION=$(tools/describe)
- name: build mpy-cross
run: make -j2 -C mpy-cross

View File

@ -14,33 +14,32 @@ concurrency:
jobs:
pre-commit:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2.2.0
- uses: actions/checkout@v3
- name: Set up Python 3
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: "3.x"
python-version: "3.10"
- name: Install deps
run: |
sudo apt-add-repository -y -u ppa:pybricks/ppa
sudo apt-get install -y gettext uncrustify
pip3 install black polib pyyaml
- name: Populate selected submodules
run: git submodule update --init extmod/ulab
- name: Set PY
run: echo >>$GITHUB_ENV PY="$(python -c 'import hashlib, sys;print(hashlib.sha256(sys.version.encode()+sys.executable.encode()).hexdigest())')"
- uses: actions/cache@v2
- uses: actions/cache@v3
with:
path: ~/.cache/pre-commit
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
- uses: pre-commit/action@v1.1.0
- uses: pre-commit/action@v3.0.0
- name: Make patch
if: failure()
run: git diff > ~/pre-commit.patch
- name: Upload patch
if: failure()
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: patch
path: ~/pre-commit.patch

52
.gitmodules vendored
View File

@ -146,9 +146,9 @@
[submodule "ports/espressif/esp-idf"]
path = ports/espressif/esp-idf
url = https://github.com/adafruit/esp-idf.git
branch = circuitpython-v4.4
branch = circuitpython8
[submodule "ports/espressif/certificates/nina-fw"]
path = ports/espressif/certificates/nina-fw
path = lib/certificates/nina-fw
url = https://github.com/adafruit/nina-fw.git
[submodule "frozen/Adafruit_CircuitPython_ST7789"]
path = frozen/Adafruit_CircuitPython_ST7789
@ -196,6 +196,9 @@
url = https://github.com/raspberrypi/rpi-firmware.git
branch = master
shallow = true
[submodule "lib/adafruit_floppy"]
path = lib/adafruit_floppy
url = https://github.com/adafruit/Adafruit_Floppy
[submodule "ports/stm/st_driver/cmsis_device_f4"]
path = ports/stm/st_driver/cmsis_device_f4
url = https://github.com/STMicroelectronics/cmsis_device_f4.git
@ -277,3 +280,48 @@
[submodule "ports/stm/st_driver/stm32f4xx_hal_driver"]
path = ports/stm/st_driver/stm32f4xx_hal_driver
url = https://github.com/adafruit/stm32f4xx_hal_driver.git
[submodule "frozen/Adafruit_CircuitPython_PortalBase"]
path = frozen/Adafruit_CircuitPython_PortalBase
url = https://github.com/adafruit/Adafruit_CircuitPython_PortalBase.git
[submodule "frozen/Adafruit_CircuitPython_FakeRequests"]
path = frozen/Adafruit_CircuitPython_FakeRequests
url = https://github.com/adafruit/Adafruit_CircuitPython_FakeRequests.git
[submodule "frozen/pew-pewpew-lcd"]
path = frozen/pew-pewpew-lcd
url = https://github.com/pypewpew/pew-pewpew-lcd.git
[submodule "frozen/mixgo_cp_lib"]
path = frozen/mixgo_cp_lib
url = https://github.com/dahanzimin/circuitpython_lib.git
[submodule "frozen/Adafruit_CircuitPython_IS31FL3731"]
path = frozen/Adafruit_CircuitPython_IS31FL3731
url = https://github.com/adafruit/Adafruit_CircuitPython_IS31FL3731.git
[submodule "frozen/Adafruit_CircuitPython_Ticks"]
path = frozen/Adafruit_CircuitPython_Ticks
url = https://github.com/adafruit/Adafruit_CircuitPython_Ticks.git
[submodule "frozen/Adafruit_CircuitPython_asyncio"]
path = frozen/Adafruit_CircuitPython_asyncio
url = https://github.com/adafruit/Adafruit_CircuitPython_asyncio.git
[submodule "frozen/circuitpython_ef_music"]
path = frozen/circuitpython_ef_music
url = https://github.com/elecfreaks/circuitpython_ef_music.git
[submodule "frozen/circuitpython_picoed"]
path = frozen/circuitpython_picoed
url = https://github.com/elecfreaks/circuitpython_picoed.git
[submodule "ports/espressif/esp32-camera"]
path = ports/espressif/esp32-camera
url = https://github.com/adafruit/esp32-camera/
[submodule "ports/raspberrypi/lib/cyw43-driver"]
path = ports/raspberrypi/lib/cyw43-driver
url = https://github.com/georgerobotics/cyw43-driver.git
[submodule "ports/raspberrypi/lib/lwip"]
path = ports/raspberrypi/lib/lwip
url = https://github.com/lwip-tcpip/lwip.git
[submodule "lib/mbedtls"]
path = lib/mbedtls
url = https://github.com/ARMmbed/mbedtls.git
[submodule "frozen/Adafruit_CircuitPython_UC8151D"]
path = frozen/Adafruit_CircuitPython_UC8151D
url = https://github.com/adafruit/Adafruit_CircuitPython_UC8151D
[submodule "frozen/Adafruit_CircuitPython_SSD1680"]
path = frozen/Adafruit_CircuitPython_SSD1680
url = https://github.com/adafruit/Adafruit_CircuitPython_SSD1680

View File

@ -10,7 +10,7 @@ repos:
- id: end-of-file-fixer
exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|ports/espressif/esp-idf-config/.*|ports/espressif/boards/.*/sdkconfig)'
- id: trailing-whitespace
exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*)'
exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|lib/mbedtls_errors/.*)'
- repo: local
hooks:
- id: translations

View File

@ -9,16 +9,15 @@
version: 2
build:
os: ubuntu-20.04
tools:
python: "3"
submodules:
include:
- extmod/ulab
os: ubuntu-20.04
tools:
python: "3"
jobs:
post_install:
- python tools/ci_fetch_deps.py docs HEAD
formats:
- pdf
- pdf
python:
install:

View File

@ -35,6 +35,8 @@ Failing to install these will prevent from properly building.
pip3 install -r requirements-dev.txt
If you run into an error installing minify_html, you may need to install `rust`.
### mpy-cross
As part of the build process, mpy-cross is needed to compile .py files into .mpy files.
@ -70,7 +72,7 @@ The test suite in the top level `tests` directory. It needs the unix port to ru
Then you can run the test suite:
cd ../../tests
./run-tests
./run-tests.py
A successful run will say something like

76
LICENSE
View File

@ -1,6 +1,6 @@
The MIT License (MIT)
MIT License
Copyright (c) 2013-2021 Damien P. George
Copyright (c) 2013-2022 Damien P. George and others
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -9,77 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
--------------------------------------------------------------------------------
Unless specified otherwise (see below), the above license and copyright applies
to all files in this repository.
Individual files may include additional copyright holders.
The various ports of MicroPython may include third-party software that is
licensed under different terms. These licenses are summarised in the tree
below, please refer to these files and directories for further license and
copyright information. Note that (L)GPL-licensed code listed below is only
used during the build process and is not part of the compiled source code.
/ (MIT)
/drivers
/cc3000 (BSD-3-clause)
/cc3100 (BSD-3-clause)
/wiznet5k (BSD-3-clause)
/lib
/asf4 (Apache-2.0)
/axtls (BSD-3-clause)
/config
/scripts
/config (GPL-2.0-or-later)
/Rules.mak (GPL-2.0)
/berkeley-db-1xx (BSD-4-clause)
/btstack (See btstack/LICENSE)
/cmsis (BSD-3-clause)
/crypto-algorithms (NONE)
/libhydrogen (ISC)
/littlefs (BSD-3-clause)
/lwip (BSD-3-clause)
/mynewt-nimble (Apache-2.0)
/nrfx (BSD-3-clause)
/nxp_driver (BSD-3-Clause)
/oofatfs (BSD-1-clause)
/pico-sdk (BSD-3-clause)
/re15 (BSD-3-clause)
/stm32lib (BSD-3-clause)
/tinytest (BSD-3-clause)
/tinyusb (MIT)
/uzlib (Zlib)
/logo (uses OFL-1.1)
/ports
/cc3200
/hal (BSD-3-clause)
/simplelink (BSD-3-clause)
/FreeRTOS (GPL-2.0 with FreeRTOS exception)
/stm32
/usbd*.c (MCD-ST Liberty SW License Agreement V2)
/stm32_it.* (MIT + BSD-3-clause)
/system_stm32*.c (MIT + BSD-3-clause)
/boards
/startup_stm32*.s (BSD-3-clause)
/*/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
/dfu.py (LGPL-3.0-only)
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

85
LICENSE_MicroPython Normal file
View File

@ -0,0 +1,85 @@
The MIT License (MIT)
Copyright (c) 2013-2022 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
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
--------------------------------------------------------------------------------
Unless specified otherwise (see below), the above license and copyright applies
to all files in this repository.
Individual files may include additional copyright holders.
The various ports of MicroPython may include third-party software that is
licensed under different terms. These licenses are summarised in the tree
below, please refer to these files and directories for further license and
copyright information. Note that (L)GPL-licensed code listed below is only
used during the build process and is not part of the compiled source code.
/ (MIT)
/drivers
/cc3000 (BSD-3-clause)
/cc3100 (BSD-3-clause)
/wiznet5k (BSD-3-clause)
/lib
/asf4 (Apache-2.0)
/axtls (BSD-3-clause)
/config
/scripts
/config (GPL-2.0-or-later)
/Rules.mak (GPL-2.0)
/berkeley-db-1xx (BSD-4-clause)
/btstack (See btstack/LICENSE)
/cmsis (BSD-3-clause)
/crypto-algorithms (NONE)
/libhydrogen (ISC)
/littlefs (BSD-3-clause)
/lwip (BSD-3-clause)
/mynewt-nimble (Apache-2.0)
/nrfx (BSD-3-clause)
/nxp_driver (BSD-3-Clause)
/oofatfs (BSD-1-clause)
/pico-sdk (BSD-3-clause)
/re15 (BSD-3-clause)
/stm32lib (BSD-3-clause)
/tinytest (BSD-3-clause)
/tinyusb (MIT)
/uzlib (Zlib)
/logo (uses OFL-1.1)
/ports
/cc3200
/hal (BSD-3-clause)
/simplelink (BSD-3-clause)
/FreeRTOS (GPL-2.0 with FreeRTOS exception)
/stm32
/usbd*.c (MCD-ST Liberty SW License Agreement V2)
/stm32_it.* (MIT + BSD-3-clause)
/system_stm32*.c (MIT + BSD-3-clause)
/boards
/startup_stm32*.s (BSD-3-clause)
/*/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
/dfu.py (LGPL-3.0-only)

View File

@ -61,6 +61,7 @@ TRANSLATE_SOURCES_EXC = -path "ports/*/build-*" \
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " fetch-submodules to fetch dependencies from submodules, run this right after you clone the repo"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"

View File

@ -84,15 +84,19 @@ common set of requirements.
If you'd like to use the term "CircuitPython" and Blinka for your product here is what we ask:
* Your product is supported by the primary
- Your product is supported by the primary
`"adafruit/circuitpython" <https://github.com/adafruit/circuitpython>`_ repo. This way we can
update any custom code as we update the CircuitPython internals.
* Your product is listed on `circuitpython.org <https://circuitpython.org>`__ (source
- Your product is listed on `circuitpython.org <https://circuitpython.org>`__ (source
`here <https://github.com/adafruit/circuitpython-org/>`_). This is to ensure that a user of your
product can always download the latest version of CircuitPython from the standard place.
* Your product has a user accessible USB plug which appears as a CIRCUITPY drive when plugged in
AND/OR provides file and serial access over Bluetooth Low Energy. Boards that do not support USB
should be clearly marked as BLE-only CircuitPython.
- Your product supports at least one standard "`Workflow <https://docs.circuitpython.org/en/latest/docs/workflows.html>`__" for serial and file access:
- With a user accessible USB plug which appears as a CIRCUITPY drive when plugged in.
- With file and serial access over Bluetooth Low Energy using the BLE Workflow.
- With file access over WiFi using the WiFi Workflow with serial access over USB and/or WebSocket.
- Boards that do not support the USB Workflow should be clearly marked.
If you choose not to meet these requirements, then we ask you call your version of CircuitPython
something else (for example, SuperDuperPython) and not use the Blinka logo. You can say it is
@ -120,7 +124,7 @@ Behavior
make each file independent from each other.
- ``boot.py`` runs only once on start up before
USB is initialized. This lays the ground work for configuring USB at
workflows are initialized. This lays the ground work for configuring USB at
startup rather than it being fixed. Since serial is not available,
output is written to ``boot_out.txt``.
- ``code.py`` (or ``main.py``) is run after every reload until it
@ -135,7 +139,10 @@ Behavior
possible to fix code that causes nasty crashes by making it available through mass storage after
the crash. A reset (the button) is needed after it's fixed to get back into normal mode.
- RGB status LED indicating CircuitPython state.
- Re-runs ``code.py`` or other main file after file system writes over USB mass storage. (Disable with
- One green flash - code completed without error.
- Two red flashes - code ended due to an exception.
- Three yellow flashes - safe mode. May be due to CircuitPython internal error.
- Re-runs ``code.py`` or other main file after file system writes by a workflow. (Disable with
``supervisor.disable_autoreload()``)
- Autoreload is disabled while the REPL is active.
- Main is one of these: ``code.txt``, ``code.py``, ``main.py``,
@ -213,7 +220,7 @@ Supported Support status
================ ============================================================
atmel-samd ``SAMD21`` stable | ``SAMD51`` stable
cxd56 stable
espressif ``ESP32-C3`` beta | ``ESP32-S2`` stable | ``ESP32-S3`` beta
espressif ``ESP32`` beta | ``ESP32-C3`` beta | ``ESP32-S2`` stable | ``ESP32-S3`` beta
litex alpha
mimxrt10xx alpha
nrf stable

19
conf.py
View File

@ -24,12 +24,15 @@ import subprocess
import sys
import urllib.parse
import time
import pathlib
from collections import defaultdict
from sphinx.transforms import SphinxTransform
from docutils import nodes
from sphinx import addnodes
tools_describe = str(pathlib.Path(__file__).parent / "tools/describe")
# 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.
@ -49,10 +52,14 @@ subprocess.check_output(["make", "stubs"])
#modules_support_matrix = shared_bindings_matrix.support_matrix_excluded_boards()
modules_support_matrix = shared_bindings_matrix.support_matrix_by_board()
modules_support_matrix_reverse = defaultdict(list)
for board, modules in modules_support_matrix.items():
for module in modules:
for board, matrix_info in modules_support_matrix.items():
for module in matrix_info["modules"]:
modules_support_matrix_reverse[module].append(board)
modules_support_matrix_reverse = dict((module, sorted(boards)) for module, boards in modules_support_matrix_reverse.items())
modules_support_matrix_reverse = dict(
(module, sorted(boards))
for module, boards in modules_support_matrix_reverse.items()
)
html_context = {
'support_matrix': modules_support_matrix,
@ -80,7 +87,7 @@ extensions = [
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['templates']
templates_path = ['templates', "docs/templates"]
# The suffix of source filenames.
source_suffix = {
@ -129,7 +136,7 @@ copyright = f'2014-{current_date.tm_year}, MicroPython & CircuitPython contribut
final_version = ""
git_describe = subprocess.run(
["git", "describe", "--dirty", "--tags"],
[tools_describe],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
encoding="utf-8"
@ -192,6 +199,7 @@ exclude_patterns = ["**/build*",
"ports/cxd56/spresense-exported-sdk",
"ports/espressif/certificates",
"ports/espressif/esp-idf",
"ports/espressif/esp32-camera",
"ports/espressif/.idf_tools",
"ports/espressif/peripherals",
"ports/litex/hw",
@ -205,6 +213,7 @@ exclude_patterns = ["**/build*",
"ports/nrf/peripherals",
"ports/nrf/usb",
"ports/raspberrypi/sdk",
"ports/raspberrypi/lib",
"ports/stm/st_driver",
"ports/stm/packages",
"ports/stm/peripherals",

@ -1 +1 @@
Subproject commit 266ea20ed80104c315dcb124b482fa5f9f48cdec
Subproject commit 2d292ad4e67890d4b85b027431ba9fef7bf561fd

View File

@ -49,6 +49,10 @@
#include "shared-bindings/_bleio/ScanEntry.h"
#include "shared-bindings/time/__init__.h"
#if CIRCUITPY_DOTENV
#include "shared-module/dotenv/__init__.h"
#endif
#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION))
#define SEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000000) / (RESOLUTION))
#define UNITS_TO_SEC(TIME, RESOLUTION) (((TIME)*(RESOLUTION)) / 1000000)
@ -278,17 +282,27 @@ char default_ble_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0
// Get various values and limits set by the adapter.
// Set event mask.
STATIC void bleio_adapter_hci_init(bleio_adapter_obj_t *self) {
mp_int_t name_len = 0;
const size_t len = sizeof(default_ble_name);
#if CIRCUITPY_DOTENV
char ble_name[32];
name_len = dotenv_get_key("/.env", "CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name) - 1);
if (name_len > 0) {
self->name = mp_obj_new_str(ble_name, (size_t)name_len);
}
#endif
bt_addr_t addr;
hci_check_error(hci_read_bd_addr(&addr));
if (name_len <= 0) {
name_len = sizeof(default_ble_name);
bt_addr_t addr;
hci_check_error(hci_read_bd_addr(&addr));
default_ble_name[len - 4] = nibble_to_hex_lower[addr.val[1] >> 4 & 0xf];
default_ble_name[len - 3] = nibble_to_hex_lower[addr.val[1] & 0xf];
default_ble_name[len - 2] = nibble_to_hex_lower[addr.val[0] >> 4 & 0xf];
default_ble_name[len - 1] = nibble_to_hex_lower[addr.val[0] & 0xf];
self->name = mp_obj_new_str(default_ble_name, len);
default_ble_name[name_len - 4] = nibble_to_hex_lower[addr.val[1] >> 4 & 0xf];
default_ble_name[name_len - 3] = nibble_to_hex_lower[addr.val[1] & 0xf];
default_ble_name[name_len - 2] = nibble_to_hex_lower[addr.val[0] >> 4 & 0xf];
default_ble_name[name_len - 1] = nibble_to_hex_lower[addr.val[0] & 0xf];
self->name = mp_obj_new_str(default_ble_name, (uint8_t)name_len);
}
// Get version information.
if (hci_read_local_version(&self->hci_version, &self->hci_revision, &self->lmp_version,

View File

@ -57,9 +57,9 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self,
self->value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len);
const mp_int_t max_length_max = 512;
if (max_length < 0 || max_length > max_length_max) {
mp_raise_ValueError(translate("max_length must be <= 512"));
}
mp_arg_validate_int_range(max_length, 0, max_length_max, MP_QSTR_max_length);
self->max_length = max_length;
self->fixed_length = fixed_length;

View File

@ -93,6 +93,7 @@ bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer
void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_obj_t *self) {
if (!common_hal_bleio_characteristic_buffer_deinited(self)) {
bleio_characteristic_clear_observer(self->characteristic);
ringbuf_deinit(&self->ringbuf);
}
}

View File

@ -37,13 +37,13 @@
#include "supervisor/shared/tick.h"
STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self, uint8_t *data, uint16_t len) {
if (len + sizeof(uint16_t) > ringbuf_capacity(&self->ringbuf)) {
if (len + sizeof(uint16_t) > ringbuf_size(&self->ringbuf)) {
// This shouldn't happen.
return;
}
// Push all the data onto the ring buffer.
// Make room for the new value by dropping the oldest packets first.
while (ringbuf_capacity(&self->ringbuf) - ringbuf_num_filled(&self->ringbuf) < len + sizeof(uint16_t)) {
while (ringbuf_size(&self->ringbuf) - ringbuf_num_filled(&self->ringbuf) < len + sizeof(uint16_t)) {
uint16_t packet_length;
ringbuf_get_n(&self->ringbuf, (uint8_t *)&packet_length, sizeof(uint16_t));
for (uint16_t i = 0; i < packet_length; i++) {
@ -264,5 +264,6 @@ bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self) {
void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) {
if (!common_hal_bleio_packet_buffer_deinited(self)) {
bleio_characteristic_clear_observer(self->characteristic);
ringbuf_deinit(&self->ringbuf);
}
}

View File

@ -57,6 +57,11 @@ bool vm_used_ble;
// }
// }
void bleio_user_reset() {
// HCI doesn't support the BLE workflow so just do a full reset.
bleio_reset();
}
// Turn off BLE on a reset or reload.
void bleio_reset() {
// Create a UUID object for all CCCD's.

View File

@ -44,6 +44,7 @@
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h"
#include "supervisor/shared/tick.h"
#include "supervisor/shared/translate/translate.h"
STATIC uint16_t max_mtu = BT_ATT_DEFAULT_LE_MTU; // 23
STATIC unsigned long timeout = 5000;

View File

@ -1,9 +1,8 @@
MicroPython & CircuitPython license information
===============================================
# MicroPython & CircuitPython License
The MIT License (MIT)
MIT License
Copyright (c) 2013-2017 Damien P. George, and others
Copyright (c) 2013-2022 Damien P. George and others
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -12,13 +11,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -141,7 +141,7 @@ statement will ensure hardware isn't enabled longer than needed.
Verify your device
--------------------------------------------------------------------------------
Whenever possible, make sure device you are talking to is the device you expect.
Whenever possible, make sure the device you are talking to is the device you expect.
If not, raise a RuntimeError. Beware that I2C addresses can be identical on
different devices so read registers you know to make sure they match your
expectation. Validating this upfront will help catch mistakes.
@ -202,10 +202,10 @@ interchangeably with the CPython name. This is confusing. Instead, think up a
new name that is related to the extra functionality you are adding.
For example, storage mounting and unmounting related functions were moved from
``uos`` into a new `storage` module. Terminal related functions were moved into
`multiterminal`. These names better match their functionality and do not
conflict with CPython names. Make sure to check that you don't conflict with
CPython libraries too. That way we can port the API to CPython in the future.
``uos`` into a new `storage` module. These names better match their
functionality and do not conflict with CPython names. Make sure to check that
you don't conflict with CPython libraries too. That way we can port the API to
CPython in the future.
Example
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -213,7 +213,7 @@ Example
When adding extra functionality to CircuitPython to mimic what a normal
operating system would do, either copy an existing CPython API (for example file
writing) or create a separate module to achieve what you want. For example,
mounting and unmount drives is not a part of CPython so it should be done in a
mounting and unmounting drives is not a part of CPython so it should be done in a
module, such as a new ``storage`` module, that is only available in CircuitPython.
That way when someone moves the code to CPython they know what parts need to be
adapted.
@ -309,7 +309,7 @@ following structure:
param_type
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The type of the parameter. This could be among other `int`, `float`, `str` `bool`, etc.
The type of the parameter. This could be, among others, ``int``, ``float``, ``str``, ``bool``, etc.
To document an object in the CircuitPython domain, you need to include a ``~`` before the
definition as shown in the following example:
@ -494,6 +494,45 @@ backticks ``:class:`~adafruit_motor.servo.Servo```. You must also add the refer
"adafruit_motor": ("https://circuitpython.readthedocs.io/projects/motor/en/latest/", None,),
Use ``adafruit_register`` when possible
--------------------------------------------------------------------------------
`Register <https://github.com/adafruit/Adafruit_CircuitPython_Register>`_ is
a foundational library that manages packing and unpacking data from I2C device
registers. There is also `Register SPI <https://github.com/adafruit/Adafruit_CircuitPython_Register_SPI>`_
for SPI devices. When possible, use one of these libraries for unpacking and
packing registers. This ensures the packing code is shared amongst all
registers (even across drivers). Furthermore, it simplifies device definitions
by making them declarative (only data.)
Values with non-consecutive bits in a register or that represent FIFO endpoints
may not map well to existing register classes. In unique cases like these, it is
ok to read and write the register directly.
*Do not* add all registers from a datasheet upfront. Instead, only add the ones
necessary for the functionality the driver exposes. Adding them all will lead to
unnecessary file size and API clutter. See `this video about outside-in design
from @tannewt <https://www.youtube.com/watch?v=3QewiyfBQh8>`_.
I2C Example
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: python
from adafruit_register import i2c_bit
from adafruit_bus_device import i2c_device
class HelloWorldDevice:
"""Device with two bits to control when the words 'hello' and 'world' are lit."""
hello = i2c_bit.RWBit(0x0, 0x0)
"""Bit to indicate if hello is lit."""
world = i2c_bit.RWBit(0x1, 0x0)
"""Bit to indicate if world is lit."""
def __init__(self, i2c, device_address=0x0):
self.i2c_device = i2c_device.I2CDevice(i2c, device_address)
Use BusDevice
--------------------------------------------------------------------------------
@ -668,8 +707,24 @@ when using ``const()``, keep in mind these general guide lines:
- Always use via an import, ex: ``from micropython import const``
- Limit use to global (module level) variables only.
- If user will not need access to variable, prefix name with a leading
underscore, ex: ``_SOME_CONST``.
- Only used when the user will not need access to variable and prefix name with
a leading underscore, ex: ``_SOME_CONST``.
Example
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: python
from adafruit_bus_device import i2c_device
from micropython import const
_DEFAULT_I2C_ADDR = const(0x42)
class Widget:
"""A generic widget."""
def __init__(self, i2c, address=_DEFAULT_I2C_ADDR):
self.i2c_device = i2c_device.I2CDevice(i2c, address)
Libraries Examples
------------------
@ -751,6 +806,16 @@ properties.
| ``sound_level`` | float | non-unit-specific sound level (monotonic but not actual decibels) |
+-----------------------+-----------------------+-------------------------------------------------------------------------+
Driver constant naming
--------------------------------------------------------------------------------
When adding variables for constant values for a driver. Do not include the
device's name in the variable name. For example, in ``adafruit_fancy123.py``,
variables should not start with ``FANCY123_``. Adding this prefix increases RAM
usage and .mpy file size because variable names are preserved. User code should
refer to these constants as ``adafruit_fancy123.HELLO_WORLD`` for clarity.
``adafruit_fancy123.FANCY123_HELLO_WORLD`` would be overly verbose.
Adding native modules
--------------------------------------------------------------------------------

58
docs/environment.rst Normal file
View File

@ -0,0 +1,58 @@
Environment Variables
=====================
CircuitPython 8.0.0 introduces support for environment variables. Environment
variables are commonly used to store "secrets" such as Wi-Fi passwords and API
keys. This method *does not* make them secure. It only separates them from the
code.
CircuitPython supports these by mimicking the `dotenv <https://github.com/theskumar/python-dotenv>`_
CPython library. Other languages such as Javascript, PHP and Ruby also have
dotenv libraries.
These libraries store environment variables in a ``.env`` file. Here is a simple
example:
.. code-block:: bash
KEY1='value1'
# Comment
KEY2='value2
is multiple lines'
CircuitPython uses the ``.env`` at the drive root (no folder) as the environment.
User code can access the values from the file using `os.getenv()`. It is
recommended to save any values used repeatedly in a variable because `os.getenv()`
will parse the ``/.env`` on every access.
CircuitPython behavior
----------------------
CircuitPython will also read the environment to configure its behavior. Other
keys are ignored by CircuitPython. Here are the keys it uses:
CIRCUITPY_BLE_NAME
~~~~~~~~~~~~~~~~~~
Default BLE name the board advertises as, including for the BLE workflow.
CIRCUITPY_RESERVED_PSRAM
~~~~~~~~~~~~~~~~~~~~~~~~
On boards with Espressif microcontrollers with PSRAM (also called SPIRAM), permanently reserve a portion of PSRAM for use by esp-idf.
This storage is removed from the CircuitPython "heap" and is available for allocation by esp-idf routines in the core instead.
Generally, only set this to a non-zero value when it is required by a specific core module.
CIRCUITPY_WEB_API_PASSWORD
~~~~~~~~~~~~~~~~~~~~~~~~~~
Password required to make modifications to the board from the Web Workflow.
CIRCUITPY_WEB_API_PORT
~~~~~~~~~~~~~~~~~~~~~~
TCP port number used for the web HTTP API. Defaults to 80 when omitted.
CIRCUITPY_WIFI_PASSWORD
~~~~~~~~~~~~~~~~~~~~~~~
Wi-Fi password used to auto connect to CIRCUITPY_WIFI_SSID.
CIRCUITPY_WIFI_SSID
~~~~~~~~~~~~~~~~~~~
Wi-Fi SSID to auto-connect to even if user code is not running.

View File

@ -22,6 +22,8 @@ Full Table of Contents
supported_ports.rst
troubleshooting.rst
drivers.rst
workflows
environment.rst
.. toctree::
:maxdepth: 1
@ -46,7 +48,7 @@ Full Table of Contents
../CONTRIBUTING
../BUILDING
../CODE_OF_CONDUCT
../license.rst
../docs/LICENSE
../WEBUSB_README
Indices and tables

View File

@ -36,3 +36,9 @@ Functions
Encode binary data in base64 format, as in `RFC 3548
<https://tools.ietf.org/html/rfc3548.html>`_. Returns the encoded data
followed by a newline character, as a bytes object.
.. function:: crc32(data, value=0, /)
Compute CRC-32, the 32-bit checksum of the bytes in *data* starting with an
initial CRC of *value*. The default initial CRC is 0. The algorithm is
consistent with the ZIP file checksum.

View File

@ -1,14 +1,24 @@
:mod:`builtins` -- builtin functions and exceptions
===================================================
.. module:: builtins
:synopsis: builtin Python functions
All builtin functions and exceptions are described here. They are also
available via ``builtins`` module.
available via the ``builtins`` module.
For more information about built-ins, see the following CPython documentation:
* `Builtin CPython Functions <https://docs.python.org/3/library/functions.html>`_
* `Builtin CPython Exceptions <https://docs.python.org/3/library/exceptions.html>`_
* `Builtin CPython Constants <https://docs.python.org/3/library/constants.html>`_
.. note:: Not all of these functions, types, exceptions, and constants are turned
on in all CircuitPython ports, for space reasons.
Functions and types
-------------------
Not all of these functions and types are turned on in all CircuitPython ports, for space reasons.
.. function:: abs()
.. function:: all()
@ -160,20 +170,34 @@ Not all of these functions and types are turned on in all CircuitPython ports, f
Exceptions
----------
.. exception:: ArithmeticError
.. exception:: AssertionError
.. exception:: AttributeError
.. exception:: BaseException
.. exception:: BrokenPipeError
.. exception:: ConnectionError
.. exception:: EOFError
.. exception:: Exception
.. exception:: ImportError
.. exception:: IndentationError
.. exception:: IndexError
.. exception:: KeyboardInterrupt
.. exception:: KeyError
.. exception:: LookupError
.. exception:: MemoryError
.. exception:: NameError
@ -182,24 +206,37 @@ Exceptions
.. exception:: OSError
.. exception:: OverflowError
.. exception:: RuntimeError
.. exception:: ReloadException
`ReloadException` is used internally to deal with soft restarts.
Not a part of the CPython standard library
.. exception:: StopAsyncIteration
.. exception:: StopIteration
.. exception:: SyntaxError
.. exception:: SystemExit
|see_cpython| :py:class:`cpython:SystemExit`.
.. exception:: TimeoutError
.. exception:: TypeError
|see_cpython| :py:class:`cpython:TypeError`.
.. exception:: UnicodeError
.. exception:: ValueError
.. exception:: ZeroDivisionError
Constants
---------
.. data:: Ellipsis
.. data:: NotImplemented

View File

@ -28,7 +28,7 @@ Classes
- The optional *flags* can be 1 to check for overflow when adding items.
As well as supporting `bool` and `len`, deque objects have the following
As well as supporting ``bool`` and ``len``, deque objects have the following
methods:
.. method:: deque.append(x)

View File

@ -21,11 +21,11 @@ For example::
import framebuf
# FrameBuffer needs 2 bytes for every RGB565 pixel
fbuf = framebuf.FrameBuffer(bytearray(10 * 100 * 2), 10, 100, framebuf.RGB565)
fbuf = framebuf.FrameBuffer(bytearray(100 * 10 * 2), 100, 10, framebuf.RGB565)
fbuf.fill(0)
fbuf.text('MicroPython!', 0, 0, 0xffff)
fbuf.hline(0, 10, 96, 0xffff)
fbuf.hline(0, 9, 96, 0xffff)
Constructors
------------

View File

@ -1,59 +0,0 @@
:mod:`hashlib` -- hashing algorithms
=====================================
.. include:: ../templates/unsupported_in_circuitpython.inc
.. module:: hashlib
:synopsis: hashing algorithms
|see_cpython_module| :mod:`cpython:hashlib`.
This module implements binary data hashing algorithms. The exact inventory
of available algorithms depends on a board. Among the algorithms which may
be implemented:
* SHA256 - The current generation, modern hashing algorithm (of SHA2 series).
It is suitable for cryptographically-secure purposes. Included in the
MicroPython core and any board is recommended to provide this, unless
it has particular code size constraints.
* SHA1 - A previous generation algorithm. Not recommended for new usages,
but SHA1 is a part of number of Internet standards and existing
applications, so boards targeting network connectivity and
interoperability will try to provide this.
* MD5 - A legacy algorithm, not considered cryptographically secure. Only
selected boards, targeting interoperability with legacy applications,
will offer this.
Constructors
------------
.. class:: hashlib.sha256([data])
Create an SHA256 hasher object and optionally feed ``data`` into it.
.. class:: hashlib.sha1([data])
Create an SHA1 hasher object and optionally feed ``data`` into it.
.. class:: hashlib.md5([data])
Create an MD5 hasher object and optionally feed ``data`` into it.
Methods
-------
.. method:: hash.update(data)
Feed more binary data into hash.
.. method:: hash.digest()
Return hash for all data passed through hash, as a bytes object. After this
method is called, more data cannot be fed into the hash any longer.
.. method:: hash.hexdigest()
This method is NOT implemented. Use ``binascii.hexlify(hash.digest())``
to achieve a similar effect.

View File

@ -19,7 +19,7 @@ limited flash memory, usually on non-Express builds:
``binascii``, ``errno``, ``json``, ``re``.
These libraries are not currently enabled in any CircuitPython build, but may be in the future:
``ctypes``, ``hashlib``, ``zlib``.
``ctypes``
.. toctree::
:maxdepth: 1
@ -31,7 +31,6 @@ These libraries are not currently enabled in any CircuitPython build, but may be
collections.rst
errno.rst
gc.rst
hashlib.rst
io.rst
json.rst
re.rst
@ -39,7 +38,6 @@ These libraries are not currently enabled in any CircuitPython build, but may be
asyncio.rst
ctypes.rst
select.rst
zlib.rst
Omitted functions in the ``string`` library
-------------------------------------------

View File

@ -76,7 +76,7 @@ Functions
.. function:: heap_locked()
Lock or unlock the heap. When locked no memory allocation can occur and a
`MemoryError` will be raised if any heap allocation is attempted.
``MemoryError`` will be raised if any heap allocation is attempted.
`heap_locked()` returns a true value if the heap is currently locked.
These functions can be nested, ie `heap_lock()` can be called multiple times

View File

@ -80,6 +80,14 @@ Constants
A mutable list of directories to search for imported modules.
.. admonition:: Difference to CPython
:class: attention
On MicroPython, an entry with the value ``".frozen"`` will indicate that import
should search :term:`frozen modules <frozen module>` at that point in the search.
If no frozen module is found then search will *not* look for a directory called
``.frozen``, instead it will continue with the next entry in ``sys.path``.
.. data:: platform
The platform that CircuitPython is running on. For OS/RTOS ports, this is

View File

@ -1,40 +0,0 @@
:mod:`zlib` -- zlib decompression
=================================
.. include:: ../templates/unsupported_in_circuitpython.inc
.. module:: zlib
:synopsis: zlib decompression
|see_cpython_module| :mod:`cpython:zlib`.
This module allows to decompress binary data compressed with
`DEFLATE algorithm <https://en.wikipedia.org/wiki/DEFLATE>`_
(commonly used in zlib library and gzip archiver). Compression
is not yet implemented.
Functions
---------
.. function:: decompress(data, wbits=0, bufsize=0, /)
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.
.. class:: DecompIO(stream, wbits=0, /)
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.
.. admonition:: Difference to CPython
:class: attention
This class is MicroPython extension. It's included on provisional
basis and may be changed considerably or removed in later versions.

View File

@ -71,7 +71,7 @@ as a natural "TODO" list. An example minimal build list is shown below:
CIRCUITPY_SDCARDIO = 0
CIRCUITPY_FRAMEBUFFERIO = 0
CIRCUITPY_FREQUENCYIO = 0
CIRCUITPY_I2CPERIPHERAL = 0
CIRCUITPY_I2CTARGET = 0
# Requires SPI, PulseIO (stub ok):
CIRCUITPY_DISPLAYIO = 0
@ -79,8 +79,6 @@ as a natural "TODO" list. An example minimal build list is shown below:
# any port once their prerequisites in common-hal are complete.
# Requires DigitalIO:
CIRCUITPY_BITBANGIO = 0
# Requires DigitalIO
CIRCUITPY_GAMEPADSHIFT = 0
# Requires neopixel_write or SPI (dotstar)
CIRCUITPY_PIXELBUF = 0
# Requires OS

View File

@ -45,12 +45,10 @@ shared-bindings/audiomp3/__init__.rst shared-bindings/audiomp3/
shared-bindings/audiopwmio/PWMAudioOut.rst shared-bindings/audiopwmio/#audiopwmio.PWMAudioOut
shared-bindings/audiopwmio/__init__.rst shared-bindings/audiopwmio/
shared-bindings/bitbangio/I2C.rst shared-bindings/bitbangio/#bitbangio.I2C
shared-bindings/bitbangio/OneWire.rst shared-bindings/bitbangio/#bitbangio.OneWire
shared-bindings/bitbangio/SPI.rst shared-bindings/bitbangio/#bitbangio.SPI
shared-bindings/bitbangio/__init__.rst shared-bindings/bitbangio/
shared-bindings/board/__init__.rst shared-bindings/board/
shared-bindings/busio/I2C.rst shared-bindings/busio/#busio.I2C
shared-bindings/busio/OneWire.rst shared-bindings/busio/#busio.OneWire
shared-bindings/busio/Parity.rst shared-bindings/busio/#busio.Parity
shared-bindings/busio/SPI.rst shared-bindings/busio/#busio.SPI
shared-bindings/busio/UART.rst shared-bindings/busio/#busio.UART
@ -82,10 +80,6 @@ shared-bindings/framebufferio/FramebufferDisplay.rst shared-bindings/framebuffer
shared-bindings/framebufferio/__init__.rst shared-bindings/framebufferio/
shared-bindings/frequencyio/FrequencyIn.rst shared-bindings/frequencyio/#frequencyio.FrequencyIn
shared-bindings/frequencyio/__init__.rst shared-bindings/frequencyio/
shared-bindings/gamepad/GamePad.rst shared-bindings/gamepad/#gamepad.GamePad
shared-bindings/gamepad/__init__.rst shared-bindings/gamepad/
shared-bindings/gamepadshift/GamePadShift.rst shared-bindings/gamepadshift/#gamepadshift.GamePadShift
shared-bindings/gamepadshift/__init__.rst shared-bindings/gamepadshift/
shared-bindings/gnss/__init__.rst shared-bindings/gnss/
shared-bindings/i2cperipheral/__init__.rst shared-bindings/i2cperipheral/
shared-bindings/i2csecondary/__init__.rst shared-bindings/i2csecondary/
@ -96,11 +90,11 @@ shared-bindings/microcontroller/Pin.rst shared-bindings/microcontroller/#microco
shared-bindings/microcontroller/Processor.rst shared-bindings/microcontroller/#microcontroller.Processor
shared-bindings/microcontroller/RunMode.rst shared-bindings/microcontroller/#microcontroller.RunMode
shared-bindings/microcontroller/__init__.rst shared-bindings/microcontroller/
shared-bindings/multiterminal/__init__.rst shared-bindings/multiterminal/
shared-bindings/neopixel_write/__init__.rst shared-bindings/neopixel_write/
shared-bindings/network/__init__.rst shared-bindings/network/
shared-bindings/nvm/ByteArray.rst shared-bindings/nvm/#nvm.ByteArray
shared-bindings/nvm/__init__.rst shared-bindings/nvm/
shared-bindings/onewireio/OneWire.rst shared-bindings/onewireio/#onewireio.OneWire
shared-bindings/os/__init__.rst shared-bindings/os/
shared-bindings/protomatter/__init__.rst shared-bindings/protomatter/
shared-bindings/ps2io/Ps2.rst shared-bindings/ps2io/#ps2io.Ps2

View File

@ -27,12 +27,13 @@ import pathlib
import re
import subprocess
import sys
import functools
from concurrent.futures import ThreadPoolExecutor
SUPPORTED_PORTS = ['atmel-samd', 'broadcom', 'cxd56', 'espressif', 'litex', 'mimxrt10xx', 'nrf', 'raspberrypi', 'stm']
aliases_by_board = {
ALIASES_BY_BOARD = {
"circuitplayground_express": [
"circuitplayground_express_4h",
"circuitplayground_express_digikey_pycon2019",
@ -40,10 +41,9 @@ aliases_by_board = {
"pybadge": ["edgebadge"],
"pyportal": ["pyportal_pynt"],
"gemma_m0": ["gemma_m0_pycon2018"],
"pewpew10": ["pewpew13"],
}
aliases_brand_names = {
ALIASES_BRAND_NAMES = {
"circuitplayground_express_4h":
"Adafruit Circuit Playground Express 4-H",
"circuitplayground_express_digikey_pycon2019":
@ -54,30 +54,73 @@ aliases_brand_names = {
"Adafruit PyPortal Pynt",
"gemma_m0_pycon2018":
"Adafruit Gemma M0 PyCon 2018",
"pewpew13":
"PewPew 13",
}
additional_modules = {
"fontio": "CIRCUITPY_DISPLAYIO",
"terminalio": "CIRCUITPY_DISPLAYIO",
ADDITIONAL_MODULES = {
"_asyncio": "MICROPY_PY_UASYNCIO",
"adafruit_bus_device": "CIRCUITPY_BUSDEVICE",
"adafruit_pixelbuf": "CIRCUITPY_PIXELBUF"
"adafruit_pixelbuf": "CIRCUITPY_PIXELBUF",
"array": "CIRCUITPY_ARRAY",
# always available, so depend on something that's always 1.
"builtins": "CIRCUITPY",
"collections": "CIRCUITPY_COLLECTIONS",
"fontio": "CIRCUITPY_DISPLAYIO",
"io": "CIRCUITPY_IO",
"select": "MICROPY_PY_USELECT_SELECT",
"terminalio": "CIRCUITPY_DISPLAYIO",
"sys": "CIRCUITPY_SYS",
"usb": "CIRCUITPY_USB_HOST",
}
MODULES_NOT_IN_SHARED_BINDINGS = ["_asyncio", "array", "binascii", "builtins", "collections", "errno", "json", "re", "select", "sys", "ulab"]
FROZEN_EXCLUDES = ["examples", "docs", "tests", "utils", "conf.py", "setup.py"]
"""Files and dirs at the root of a frozen directory that should be ignored.
This is the same list as in the preprocess_frozen_modules script."""
repository_urls = {}
"""Cache of repository URLs for frozen modules."""
root_dir = pathlib.Path(__file__).resolve().parent.parent
def get_circuitpython_root_dir():
""" The path to the root './circuitpython' directory
""" The path to the root './circuitpython' directory.
"""
file_path = pathlib.Path(__file__).resolve()
root_dir = file_path.parent.parent
return root_dir
def get_shared_bindings():
""" Get a list of modules in shared-bindings based on folder names
""" Get a list of modules in shared-bindings based on folder names.
"""
shared_bindings_dir = get_circuitpython_root_dir() / "shared-bindings"
return [item.name for item in shared_bindings_dir.iterdir()] + ["binascii", "errno", "json", "re", "ulab"]
return [item.name for item in shared_bindings_dir.iterdir()] + MODULES_NOT_IN_SHARED_BINDINGS
def get_board_mapping():
"""
Compiles the list of boards from the directories, with aliases and mapping
to the port.
"""
boards = {}
for port in SUPPORTED_PORTS:
board_path = root_dir / "ports" / port / "boards"
for board_path in os.scandir(board_path):
if board_path.is_dir():
board_files = os.listdir(board_path.path)
board_id = board_path.name
aliases = ALIASES_BY_BOARD.get(board_path.name, [])
boards[board_id] = {
"port": port,
"download_count": 0,
"aliases": aliases,
}
for alias in aliases:
boards[alias] = {
"port": port,
"download_count": 0,
"alias": True,
"aliases": [],
}
return boards
def read_mpconfig():
@ -104,8 +147,8 @@ def build_module_map():
full_build = False
for module in modules:
full_name = module
if module in additional_modules:
search_identifier = additional_modules[module]
if module in ADDITIONAL_MODULES:
search_identifier = ADDITIONAL_MODULES[module]
else:
search_identifier = 'CIRCUITPY_'+module.lstrip("_").upper()
re_pattern = f"{re.escape(search_identifier)}\s*\??=\s*(.+)"
@ -162,6 +205,69 @@ def get_settings_from_makefile(port_dir, board_name):
return settings
def get_repository_url(directory):
if directory in repository_urls:
return repository_urls[directory]
readme = None
for readme_path in (
os.path.join(directory, "README.rst"),
os.path.join(os.path.dirname(directory), "README.rst")
):
if os.path.exists(readme_path):
readme = readme_path
break
path = None
if readme:
with open(readme, "r") as fp:
for line in fp.readlines():
if m := re.match("\s+:target:\s+(http\S+(docs.circuitpython|readthedocs)\S+)\s*", line):
path = m.group(1)
break
if m := re.search("<(http[^>]+)>", line):
path = m.group(1)
break
if path is None:
contents = subprocess.run(
["git", "remote", "get-url", "origin"],
encoding="utf-8",
errors="replace",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=directory
)
path = contents.stdout.strip()
repository_urls[directory] = path
return path
def frozen_modules_from_dirs(frozen_mpy_dirs, withurl):
"""
Go through the list of frozen directories and extract the python modules.
Paths are of the type:
$(TOP)/frozen/Adafruit_CircuitPython_CircuitPlayground
$(TOP)/frozen/circuitpython-stage/meowbit
Python modules are at the root of the path, and are python files or directories
containing python files. Except the ones in the FROZEN_EXCLUDES list.
"""
frozen_modules = []
for frozen_path in filter(lambda x: x, frozen_mpy_dirs.split(" ")):
source_dir = get_circuitpython_root_dir() / frozen_path[7:]
url_repository = get_repository_url(source_dir)
for sub in source_dir.glob("*"):
if sub.name in FROZEN_EXCLUDES:
continue
if sub.name.endswith(".py"):
if withurl:
frozen_modules.append((sub.name[:-3], url_repository))
else:
frozen_modules.append(sub.name[:-3])
continue
if next(sub.glob("**/*.py"), None): # tests if not empty
if withurl:
frozen_modules.append((sub.name, url_repository))
else:
frozen_modules.append(sub.name)
return frozen_modules
def lookup_setting(settings, key, default=''):
while True:
value = settings.get(key, default)
@ -170,6 +276,7 @@ def lookup_setting(settings, key, default=''):
key = value[2:-1]
return value
@functools.cache
def all_ports_all_boards(ports=SUPPORTED_PORTS):
for port in ports:
@ -179,7 +286,7 @@ def all_ports_all_boards(ports=SUPPORTED_PORTS):
continue
yield (port, entry)
def support_matrix_by_board(use_branded_name=True):
def support_matrix_by_board(use_branded_name=True, withurl=True):
""" Compiles a list of the available core modules available for each
board.
"""
@ -207,25 +314,50 @@ def support_matrix_by_board(use_branded_name=True):
board_modules.append(base[module]['name'])
board_modules.sort()
if "CIRCUITPY_BUILD_EXTENSIONS" in settings:
board_extensions = [
extension.strip() for extension in
settings["CIRCUITPY_BUILD_EXTENSIONS"].split(",")
]
else:
raise OSError(f"Board extensions undefined: {board_name}.")
frozen_modules = []
if "FROZEN_MPY_DIRS" in settings:
frozen_modules = frozen_modules_from_dirs(settings["FROZEN_MPY_DIRS"], withurl)
if frozen_modules:
frozen_modules.sort()
# generate alias boards too
board_matrix = [(board_name, board_modules)]
if entry.name in aliases_by_board:
for alias in aliases_by_board[entry.name]:
board_matrix = [(
board_name, {
"modules": board_modules,
"frozen_libraries": frozen_modules,
"extensions": board_extensions,
}
)]
if entry.name in ALIASES_BY_BOARD:
for alias in ALIASES_BY_BOARD[entry.name]:
if use_branded_name:
if alias in aliases_brand_names:
alias = aliases_brand_names[alias]
if alias in ALIASES_BRAND_NAMES:
alias = ALIASES_BRAND_NAMES[alias]
else:
alias = alias.replace("_"," ").title()
board_matrix.append( (alias, board_modules) )
board_matrix.append((
alias, {
"modules": board_modules,
"frozen_libraries": frozen_modules,
"extensions": board_extensions,
},
))
return board_matrix # this is now a list of (board,modules)
executor = ThreadPoolExecutor(max_workers=os.cpu_count())
mapped_exec = executor.map(support_matrix, all_ports_all_boards())
# flatmap with comprehensions
boards = dict(sorted([board for matrix in mapped_exec for board in matrix]))
boards = dict(sorted([board for matrix in mapped_exec for board in matrix], key=lambda x: x[0]))
# print(json.dumps(boards, indent=2))
return boards
if __name__ == '__main__':

View File

@ -7,8 +7,21 @@
right: 10px;
top: 4px;
}
.support-matrix-table .this_module code,
.support-matrix-table .this_module span {
.support-matrix-table .reference.external {
box-sizing: border-box;
font-weight: 700;
color: #404040;
font-family: "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", Courier, monospace;
padding: 2px 5px;
background: white;
border: 1px solid #e1e4e5;
font-size: 75%;
}
.support-matrix-table .this_module,
.support-matrix-table .this_module.reference.external,
.support-matrix-table .this_module * {
background: black;
color: white;
}

View File

@ -44,14 +44,14 @@ $(() => {
var nvisible = 0;
$(".support-matrix-table tbody tr").each( (index,item) => {
var name = $(item).find("td:first-child p").html();
var modules = $(item).find("a.reference.internal");
var modules = $(item).find("code, a.reference.external");
var matching_all = true;
//
list_search.forEach((sstring) => {
var matching = (sstring[0] == "-");
for(var modi = 0; modi < modules.length; ++modi) {
module = modules[modi];
var mod_name = module.firstChild.firstChild.textContent;
var mod_name = module.firstChild.textContent;
if(sstring[0] == "-") {
if(mod_name.match(sstring.substr(1))) {
matching = false;

430
docs/workflows.md Normal file
View File

@ -0,0 +1,430 @@
# Workflows
Workflows are the process used to 1) manipulate files on the CircuitPython device and 2) interact
with the serial connection to CircuitPython. The serial connection is usually used to access the
REPL.
Starting with CircuitPython 3.x we moved to a USB-only workflow. Prior to that, we used the serial
connection alone to do the whole workflow. In CircuitPython 7.x, a BLE workflow was added with the
advantage of working with mobile devices. CircuitPython 8.x added a web workflow that works over the
local network (usually Wi-Fi) and a web browser. Other clients can also use the Web REST API. Boards
should clearly document which workflows are supported.
Code for workflows lives in `supervisor/shared`.
The workflow APIs are documented here.
## USB
These USB interfaces are enabled by default on boards with USB support. They are usable once the
device has been plugged into a host.
### CIRCUITPY drive
CircuitPython exposes a standard mass storage (MSC) interface to enable file manipulation over a
standard interface. This interface works underneath the file system at the block level so using it
excludes other types of workflows from manipulating the file system at the same time.
### CDC serial
CircuitPython exposes one CDC USB interface for CircuitPython serial. This is a standard serial
USB interface.
TODO: Document how it designates itself from the user CDC.
Setting baudrate 1200 and disconnecting will reboot into a bootloader. (Used by Arduino to trigger
a reset into bootloader.)
## BLE
The BLE workflow is enabled for nRF boards. By default, to prevent malicious access, it is disabled.
To connect to the BLE workflow, press the reset button while the status led blinks blue quickly
after the safe mode blinks. The board will restart and broadcast the file transfer service UUID
(`0xfebb`) along with the board's [Creation IDs](https://github.com/creationid/creators). This
public broadcast is done at a lower transmit level so the devices must be closer. On connection, the
device will need to pair and bond. Once bonded, the device will broadcast whenever disconnected
using a rotating key rather than a static one. Non-bonded devices won't be able to resolve it. After
connection, the central device can discover two default services. One for file transfer and one for
CircuitPython specifically that includes serial characteristics.
To change the default BLE advertising name without (or before) running user code, the desired name
can be put in the `/.env` file. The key is `CIRCUITPY_BLE_NAME`. It's limited to approximately
30 characters depending on the port's settings and will be truncated if longer.
### File Transfer API
CircuitPython uses [an open File Transfer API](https://github.com/adafruit/Adafruit_CircuitPython_BLE_File_Transfer)
to enable file system access.
### CircuitPython Service
The base UUID for the CircuitPython service is `ADAFXXXX-4369-7263-7569-7450794686e`. The `XXXX` is
replaced by the four specific digits below. The service itself is `0001`.
#### TX - `0002` / RX - `0003`
These characteristic work just like the Nordic Uart Service (NUS) but have different UUIDs to prevent
conflicts with user created NUS services.
#### Version - `0100`
Read-only characteristic that returns the UTF-8 encoded version string.
## Web
The web workflow is depends on adding Wi-Fi credentials into the `/.env` file. The keys are
`CIRCUITPY_WIFI_SSID` and `CIRCUITPY_WIFI_PASSWORD`. Once these are defined, CircuitPython will
automatically connect to the network and start the webserver used for the workflow. The webserver
is on port 80 unless overridden by `CIRCUITPY_WEB_API_PORT`. It also enables MDNS.
Here is an example `/.env`:
```bash
# To auto-connect to Wi-Fi
CIRCUITPY_WIFI_SSID='scottswifi'
CIRCUITPY_WIFI_PASSWORD='secretpassword'
# To enable modifying files from the web. Change this too!
# Leave the User field blank in the browser.
CIRCUITPY_WEB_API_PASSWORD='passw0rd'
CIRCUITPY_WEB_API_PORT=80
```
MDNS is used to resolve [`circuitpython.local`](http://circuitpython.local) to a device specific
hostname of the form `cpy-XXXXXX.local`. The `XXXXXX` is based on network MAC address. The device
also provides the MDNS service with service type `_circuitpython` and protocol `_tcp`.
### HTTP
The web server is HTTP 1.1 and may use chunked responses so that it doesn't need to precompute
content length.
The API generally consists of an HTTP method such as GET or PUT and a path. Requests and responses
also have headers. Responses will contain a status code and status text such as `404 Not Found`.
This API tries to use standard status codes to encode the status of the various operations. The
[Mozilla Developer Network HTTP docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP)
are a great reference.
#### Examples
The examples use `curl`, a common command line program for issuing HTTP requests. The examples below
use `circuitpython.local` as the easiest way to work. If you have multiple active devices, you'll
want to use the specific `cpy-XXXXXX.local` version.
The examples also use `passw0rd` as the password placeholder. Replace it with your password before
running the example.
### `/`
The root welcome page links to the file system page and also displays other CircuitPython devices
found using MDNS service discovery. This allows web browsers to find other devices from one. (All
devices will respond to `circuitpython.local` so the device redirected to may vary.)
### CORS
The web server will allow requests from `cpy-XXXXXX.local`, `127.0.0.1`, the device's IP and
`code.circuitpython.org`. (`circuitpython.local` requests will be redirected to `cpy-XXXXXX.local`.)
### File REST API
All file system related APIs are protected by HTTP basic authentication. It is *NOT* secure but will
hopefully prevent some griefing in shared settings. The password is sent unencrypted so do not reuse
a password with something important. The user field is left blank.
The password is taken from `/.env` with the key `CIRCUITPY_WEB_API_PASSWORD`. If this is unset, the
server will respond with `403 Forbidden`. When a password is set, but not provided in a request, it
will respond `401 Unauthorized`.
#### `/fs/`
The `/fs/` page will respond with a directory browsing HTML once authenticated. This page is always
gzipped. If the `Accept: application/json` header is provided, then the JSON representation of the
root will be returned.
##### OPTIONS
When requested with the `OPTIONS` method, the server will respond with CORS related headers. Most
aren't needed for API use. They are there for the web browser.
* `Access-Control-Allow-Methods` - Varies with USB state. `GET, OPTIONS` when USB is active. `GET, OPTIONS, PUT, DELETE, MOVE` otherwise.
Example:
```sh
curl -v -u :passw0rd -X OPTIONS -L --location-trusted http://circuitpython.local/fs/
```
#### `/fs/<directory path>/`
Directory paths must end with a /. Otherwise, the path is assumed to be a file.
##### GET
Returns a JSON representation of the directory.
* `200 OK` - Directory exists and JSON returned
* `401 Unauthorized` - Incorrect password
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
* `404 Not Found` - Missing directory
Returns information about each file in the directory:
* `name` - File name. No trailing `/` on directory names
* `directory` - `true` when a directory. `false` otherwise
* `modified_ns` - File modification time in nanoseconds since January 1st, 1970. May not use full resolution
* `file_size` - File size in bytes. `0` for directories
Example:
```sh
curl -v -u :passw0rd -H "Accept: application/json" -L --location-trusted http://circuitpython.local/fs/lib/hello/
```
```json
[
{
"name": "world.txt",
"directory": false,
"modified_ns": 946934328000000000,
"file_size": 12
}
]
```
##### PUT
Tries to make a directory at the given path. Request body is ignored. The custom `X-Timestamp`
header can provide a timestamp in milliseconds since January 1st, 1970 (to match JavaScript's file
time resolution) used for the directories modification time. The RTC time will used otherwise.
Returns:
* `204 No Content` - Directory exists
* `201 Created` - Directory created
* `401 Unauthorized` - Incorrect password
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
* `409 Conflict` - USB is active and preventing file system modification
* `404 Not Found` - Missing parent directory
* `500 Server Error` - Other, unhandled error
Example:
```sh
curl -v -u :passw0rd -X PUT -L --location-trusted http://circuitpython.local/fs/lib/hello/world/
```
##### Move
Moves the directory at the given path to ``X-Destination``. Also known as rename.
The custom `X-Destination` header stores the destination path of the directory.
* `201 Created` - Directory renamed
* `401 Unauthorized` - Incorrect password
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
* `404 Not Found` - Source directory not found or destination path is missing
* `409 Conflict` - USB is active and preventing file system modification
* `412 Precondition Failed` - The destination path is already in use
Example:
```sh
curl -v -u :passw0rd -X MOVE -H "X-Destination: /fs/lib/hello2/" -L --location-trusted http://circuitpython.local/fs/lib/hello/
```
##### DELETE
Deletes the directory and all of its contents.
* `204 No Content` - Directory and its contents deleted
* `401 Unauthorized` - Incorrect password
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
* `404 Not Found` - No directory
* `409 Conflict` - USB is active and preventing file system modification
Example:
```sh
curl -v -u :passw0rd -X DELETE -L --location-trusted http://circuitpython.local/fs/lib/hello2/world/
```
#### `/fs/<file path>`
##### PUT
Stores the provided content to the file path.
The custom `X-Timestamp` header can provide a timestamp in milliseconds since January 1st, 1970
(to match JavaScript's file time resolution) used for the directories modification time. The RTC
time will used otherwise.
Returns:
* `201 Created` - File created and saved
* `204 No Content` - File existed and overwritten
* `401 Unauthorized` - Incorrect password
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
* `404 Not Found` - Missing parent directory
* `409 Conflict` - USB is active and preventing file system modification
* `413 Payload Too Large` - `Expect` header not sent and file is too large
* `417 Expectation Failed` - `Expect` header sent and file is too large
* `500 Server Error` - Other, unhandled error
If the client sends the `Expect` header, the server will reply with `100 Continue` when ok.
Example:
```sh
echo "Hello world" >> test.txt
curl -v -u :passw0rd -T test.txt -L --location-trusted http://circuitpython.local/fs/lib/hello/world.txt
```
##### GET
Returns the raw file contents. `Content-Type` will be set based on extension:
* `text/plain` - `.py`, `.txt`
* `text/javascript` - `.js`
* `text/html` - `.html`
* `application/json` - `.json`
* `application/octet-stream` - Everything else
Will return:
* `200 OK` - File exists and file returned
* `401 Unauthorized` - Incorrect password
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
* `404 Not Found` - Missing file
Example:
```sh
curl -v -u :passw0rd -L --location-trusted http://circuitpython.local/fs/lib/hello/world.txt
```
##### Move
Moves the file at the given path to the ``X-Destination``. Also known as rename.
The custom `X-Destination` header stores the destination path of the file.
* `201 Created` - File renamed
* `401 Unauthorized` - Incorrect password
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
* `404 Not Found` - Source file not found or destination path is missing
* `409 Conflict` - USB is active and preventing file system modification
* `412 Precondition Failed` - The destination path is already in use
Example:
```sh
curl -v -u :passw0rd -X MOVE -H "X-Destination: /fs/lib/hello/world2.txt" -L --location-trusted http://circuitpython.local/fs/lib/hello/world.txt
```
##### DELETE
Deletes the file.
* `204 No Content` - File existed and deleted
* `401 Unauthorized` - Incorrect password
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
* `404 Not Found` - File not found
* `409 Conflict` - USB is active and preventing file system modification
Example:
```sh
curl -v -u :passw0rd -X DELETE -L --location-trusted http://circuitpython.local/fs/lib/hello/world2.txt
```
### `/cp/`
`/cp/` serves basic info about the CircuitPython device and others discovered through MDNS. It is
not protected by basic auth in case the device is someone elses.
Only `GET` requests are supported and will return `405 Method Not Allowed` otherwise.
#### `/cp/devices.json`
Returns information about other devices found on the network using MDNS.
* `total`: Total MDNS response count. May be more than in `devices` if internal limits were hit.
* `devices`: List of discovered devices.
* `hostname`: MDNS hostname
* `instance_name`: MDNS instance name. Defaults to human readable board name.
* `port`: Port of CircuitPython Web API
* `ip`: IP address
Example:
```sh
curl -v -L http://circuitpython.local/cp/devices.json
```
```json
{
"total": 1,
"devices": [
{
"hostname": "cpy-951032",
"instance_name": "Adafruit Feather ESP32-S2 TFT",
"port": 80,
"ip": "192.168.1.235"
}
]
}
```
#### `/cp/serial/`
Serves a basic serial terminal program when a `GET` request is received without the
`Upgrade: websocket` header. Otherwise the socket is upgraded to a WebSocket. See WebSockets below for more detail.
This is an authenticated endpoint in both modes.
#### `/cp/version.json`
Returns information about the device.
* `web_api_version`: Always `1`. This versions the rest of the API and new versions may not be backwards compatible.
* `version`: CircuitPython build version.
* `build_date`: CircuitPython build date.
* `board_name`: Human readable name of the board.
* `mcu_name`: Human readable name of the microcontroller.
* `board_id`: Board id used in code and on circuitpython.org.
* `creator_id`: Creator ID for the board.
* `creation_id`: Creation ID for the board, set by the creator.
* `hostname`: MDNS hostname.
* `port`: Port of CircuitPython Web Service.
* `ip`: IP address of the device.
Example:
```sh
curl -v -L http://circuitpython.local/cp/version.json
```
```json
{
"web_api_version": 1,
"version": "8.0.0-alpha.1-20-ge1d4518a9-dirty",
"build_date": "2022-06-24",
"board_name": "ESP32-S3-USB-OTG-N8",
"mcu_name": "ESP32S3",
"board_id": "espressif_esp32s3_usb_otg_n8",
"creator_id": 12346,
"creation_id": 28683,
"hostname": "cpy-f57ce8",
"port": 80,
"ip": "192.168.1.94"
}
```
#### `/code/`
The `/code/` page returns a small static html page that will pull in and load the full code editor from
[code.circuitpython.org](https://code.circuitpython.org) for a full code editor experience. Because most
of the resources reside online instead of the device, an active internet connection is required.
### Static files
* `/favicon.ico` - Blinka
* `/directory.js` - JavaScript for `/fs/`
* `/welcome.js` - JavaScript for `/`
### WebSocket
The CircuitPython serial interactions are available over a WebSocket. A WebSocket begins as a
special HTTP request that gets upgraded to a WebSocket. Authentication happens before upgrading.
WebSockets are *not* bare sockets once upgraded. Instead they have their own framing format for data.
CircuitPython can handle PING and CLOSE opcodes. All others are treated as TEXT. Data to
CircuitPython is expected to be masked UTF-8, as the spec requires. Data from CircuitPython to the
client is unmasked. It is also unbuffered so the client will get a variety of frame sizes.
Only one WebSocket at a time is supported.

View File

@ -18,7 +18,7 @@ void *memmove(void *dest, const void *src, size_t n) {
}
void *malloc(size_t n) {
void *ptr = m_malloc(n);
void *ptr = m_malloc(n, false);
return ptr;
}
void *realloc(void *ptr, size_t n) {
@ -26,7 +26,7 @@ void *realloc(void *ptr, size_t n) {
return NULL;
}
void *calloc(size_t n, size_t m) {
void *ptr = m_malloc(n * m);
void *ptr = m_malloc(n * m, false);
// memory already cleared by conservative GC
return ptr;
}
@ -51,7 +51,7 @@ int *__errno (void)
ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) {
mp_obj_base_t* o = stream;
const mp_stream_p_t *stream_p = o->type->protocol;
const mp_stream_p_t *stream_p = o->type->ext[0].protocol;
mp_uint_t out_sz = stream_p->write(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno);
if (out_sz == MP_STREAM_ERROR) {
return -1;
@ -62,7 +62,7 @@ ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) {
ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) {
mp_obj_base_t* o = stream;
const mp_stream_p_t *stream_p = o->type->protocol;
const mp_stream_p_t *stream_p = o->type->ext[0].protocol;
mp_uint_t out_sz = stream_p->read(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno);
if (out_sz == MP_STREAM_ERROR) {
return -1;
@ -73,7 +73,7 @@ ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) {
off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) {
const mp_obj_base_t* o = stream;
const mp_stream_p_t *stream_p = o->type->protocol;
const mp_stream_p_t *stream_p = o->type->ext[0].protocol;
struct mp_stream_seek_t seek_s;
seek_s.offset = offset;
seek_s.whence = whence;
@ -86,7 +86,7 @@ off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) {
int mp_stream_posix_fsync(void *stream) {
mp_obj_base_t* o = stream;
const mp_stream_p_t *stream_p = o->type->protocol;
const mp_stream_p_t *stream_p = o->type->ext[0].protocol;
mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_FLUSH, 0, &native_errno);
if (res == MP_STREAM_ERROR) {
return -1;
@ -94,7 +94,7 @@ int mp_stream_posix_fsync(void *stream) {
return res;
}
mp_obj_type_t btree_type;
mp_obj_full_type_t btree_type;
#include "extmod/modbtree.c"
@ -123,12 +123,13 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
MP_DYNRUNTIME_INIT_ENTRY
btree_type.base.type = (void*)&mp_fun_table.type_type;
btree_type.flags = MP_TYPE_FLAG_EXTENDED;
btree_type.name = MP_QSTR_btree;
btree_type.print = btree_print;
btree_type.getiter = btree_getiter;
btree_type.iternext = btree_iternext;
btree_type.binary_op = btree_binary_op;
btree_type.subscr = btree_subscr;
btree_type.ext[0].getiter = btree_getiter;
btree_type.ext[0].iternext = btree_iternext;
btree_type.ext[0].binary_op = btree_binary_op;
btree_type.ext[0].subscr = btree_subscr;
btree_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_close), MP_OBJ_FROM_PTR(&btree_close_obj) };
btree_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_flush), MP_OBJ_FROM_PTR(&btree_flush_obj) };
btree_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_get), MP_OBJ_FROM_PTR(&btree_get_obj) };

View File

@ -8,7 +8,7 @@ void *memset(void *s, int c, size_t n) {
}
#endif
mp_obj_type_t mp_type_framebuf;
mp_obj_full_type_t mp_type_framebuf;
#include "extmod/modframebuf.c"
@ -19,9 +19,10 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
MP_DYNRUNTIME_INIT_ENTRY
mp_type_framebuf.base.type = (void*)&mp_type_type;
mp_type_framebuf.flags = MP_TYPE_FLAG_EXTENDED;
mp_type_framebuf.name = MP_QSTR_FrameBuffer;
mp_type_framebuf.make_new = framebuf_make_new;
mp_type_framebuf.buffer_p.get_buffer = framebuf_get_buffer;
mp_type_framebuf.ext[0].buffer_p.get_buffer = framebuf_get_buffer;
framebuf_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill), MP_OBJ_FROM_PTR(&framebuf_fill_obj) };
framebuf_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill_rect), MP_OBJ_FROM_PTR(&framebuf_fill_rect_obj) };
framebuf_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_pixel), MP_OBJ_FROM_PTR(&framebuf_pixel_obj) };

View File

@ -8,7 +8,8 @@ void *memset(void *s, int c, size_t n) {
}
#endif
mp_obj_type_t decompio_type;
mp_obj_full_type_t decompio_type;
mp_stream_p_t decompio_stream_p;
#include "extmod/moduzlib.c"
@ -18,10 +19,14 @@ STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY
decompio_stream_p.name = MP_QSTR_protocol_stream;
decompio_stream_p.read = decompio_read;
decompio_type.base.type = mp_fun_table.type_type;
decompio_type.flags = MP_TYPE_FLAG_EXTENDED;
decompio_type.name = MP_QSTR_DecompIO;
decompio_type.make_new = decompio_make_new;
decompio_type.protocol = &decompio_stream_p;
decompio_type.ext[0].protocol = &decompio_stream_p;
decompio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) };
decompio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) };
decompio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) };

View File

@ -10,11 +10,13 @@ set(MICROPY_SOURCE_EXTMOD
${MICROPY_EXTMOD_DIR}/machine_i2c.c
${MICROPY_EXTMOD_DIR}/machine_mem.c
${MICROPY_EXTMOD_DIR}/machine_pulse.c
${MICROPY_EXTMOD_DIR}/machine_pwm.c
${MICROPY_EXTMOD_DIR}/machine_signal.c
${MICROPY_EXTMOD_DIR}/machine_spi.c
${MICROPY_EXTMOD_DIR}/modbluetooth.c
${MICROPY_EXTMOD_DIR}/modbtree.c
${MICROPY_EXTMOD_DIR}/modframebuf.c
${MICROPY_EXTMOD_DIR}/modnetwork.c
${MICROPY_EXTMOD_DIR}/modonewire.c
${MICROPY_EXTMOD_DIR}/moduasyncio.c
${MICROPY_EXTMOD_DIR}/modubinascii.c
@ -23,9 +25,11 @@ set(MICROPY_SOURCE_EXTMOD
${MICROPY_EXTMOD_DIR}/moduhashlib.c
${MICROPY_EXTMOD_DIR}/moduheapq.c
${MICROPY_EXTMOD_DIR}/modujson.c
${MICROPY_EXTMOD_DIR}/moduplatform.c
${MICROPY_EXTMOD_DIR}/modurandom.c
${MICROPY_EXTMOD_DIR}/modure.c
${MICROPY_EXTMOD_DIR}/moduselect.c
${MICROPY_EXTMOD_DIR}/modusocket.c
${MICROPY_EXTMOD_DIR}/modussl_axtls.c
${MICROPY_EXTMOD_DIR}/modussl_mbedtls.c
${MICROPY_EXTMOD_DIR}/modutimeq.c

View File

@ -47,7 +47,7 @@ void __dbpanic(DB *db) {
STATIC mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) {
mp_obj_btree_t *o = m_new_obj(mp_obj_btree_t);
o->base.type = &btree_type;
o->base.type = (mp_obj_type_t *)&btree_type;
o->stream = stream;
o->db = db;
o->start_key = mp_const_none;

View File

@ -622,7 +622,7 @@ STATIC const mp_obj_type_t mp_type_framebuf = {
// this factory function is provided for backwards compatibility with old FrameBuffer1 class
STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args) {
mp_obj_framebuf_t *o = m_new_obj(mp_obj_framebuf_t);
o->base.type = &mp_type_framebuf;
o->base.type = (mp_obj_type_t *)&mp_type_framebuf;
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE);

View File

@ -9,6 +9,8 @@
#include "py/obj.h"
#include "py/mphal.h"
#if MICROPY_PY_ONEWIRE
/******************************************************************************/
// Low-level 1-Wire routines
@ -139,3 +141,5 @@ const mp_obj_module_t mp_module_onewire = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&onewire_module_globals,
};
#endif // MICROPY_PY_ONEWIRE

View File

@ -29,6 +29,12 @@
#include "py/pairheap.h"
#include "py/mphal.h"
#if CIRCUITPY && !(defined(__unix__) || defined(__APPLE__))
#include "shared-bindings/supervisor/__init__.h"
#endif
#include "supervisor/shared/translate/translate.h"
#if MICROPY_PY_UASYNCIO
// Used when task cannot be guaranteed to be non-NULL.
@ -59,19 +65,31 @@ STATIC const mp_obj_type_t task_queue_type;
STATIC const mp_obj_type_t task_type;
STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf);
/******************************************************************************/
// Ticks for task ordering in pairing heap
#define _TICKS_PERIOD (1lu << 29)
#define _TICKS_MAX (_TICKS_PERIOD - 1)
#define _TICKS_HALFPERIOD (_TICKS_PERIOD >> 1)
#if !CIRCUITPY || (defined(__unix__) || defined(__APPLE__))
STATIC mp_obj_t ticks(void) {
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & _TICKS_MAX);
}
#else
// We don't share the implementation above because our supervisor_ticks_ms
// starts the epoch about 65 seconds before the first overflow (see
// shared-bindings/supervisor/__init__.c). We assume/require that
// supervisor.ticks_ms is picked as the ticks implementation under
// CircuitPython for the Python-coded bits of asyncio.
#define ticks() supervisor_ticks_ms()
#endif
STATIC mp_int_t ticks_diff(mp_obj_t t1_in, mp_obj_t t0_in) {
mp_uint_t t0 = MP_OBJ_SMALL_INT_VALUE(t0_in);
mp_uint_t t1 = MP_OBJ_SMALL_INT_VALUE(t1_in);
mp_int_t diff = ((t1 - t0 + MICROPY_PY_UTIME_TICKS_PERIOD / 2) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1))
- MICROPY_PY_UTIME_TICKS_PERIOD / 2;
mp_int_t diff = ((t1 - t0 + _TICKS_HALFPERIOD) & _TICKS_MAX) - _TICKS_HALFPERIOD;
return diff;
}
@ -225,6 +243,11 @@ STATIC mp_obj_t task_cancel(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_cancel_obj, task_cancel);
STATIC mp_obj_t task_await(mp_obj_t self_in) {
return task_getiter(self_in, NULL);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_await_obj, task_await);
STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
if (dest[0] == MP_OBJ_NULL) {
@ -243,6 +266,9 @@ STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
dest[1] = self_in;
} else if (attr == MP_QSTR_ph_key) {
dest[0] = self->ph_key;
} else if (attr == MP_QSTR___await__) {
dest[0] = MP_OBJ_FROM_PTR(&task_await_obj);
dest[1] = self_in;
}
} else if (dest[1] != MP_OBJ_NULL) {
// Store
@ -272,8 +298,13 @@ STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
STATIC mp_obj_t task_iternext(mp_obj_t self_in) {
mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
if (TASK_IS_DONE(self)) {
// Task finished, raise return value to caller so it can continue.
nlr_raise(self->data);
if (self->data == mp_const_none) {
// Task finished but has already been sent to the loop's exception handler.
mp_raise_StopIteration(MP_OBJ_NULL);
} else {
// Task finished, raise return value to caller so it can continue.
nlr_raise(self->data);
}
} else {
// Put calling task on waiting queue.
mp_obj_t cur_task = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task));
@ -301,7 +332,11 @@ STATIC const mp_obj_type_t task_type = {
// C-level uasyncio module
STATIC const mp_rom_map_elem_t mp_module_uasyncio_globals_table[] = {
#if CIRCUITPY
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__asyncio) },
#else
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__uasyncio) },
#endif
{ MP_ROM_QSTR(MP_QSTR_TaskQueue), MP_ROM_PTR(&task_queue_type) },
{ MP_ROM_QSTR(MP_QSTR_Task), MP_ROM_PTR(&task_type) },
};
@ -312,4 +347,6 @@ const mp_obj_module_t mp_module_uasyncio = {
.globals = (mp_obj_dict_t *)&mp_module_uasyncio_globals,
};
MP_REGISTER_MODULE(MP_QSTR__asyncio, mp_module_uasyncio, MICROPY_PY_UASYNCIO);
#endif // MICROPY_PY_UASYNCIO

View File

@ -11,6 +11,8 @@
#include "py/runtime.h"
#include "py/binary.h"
#include "supervisor/shared/translate/translate.h"
static void check_not_unicode(const mp_obj_t arg) {
#if MICROPY_CPYTHON_COMPAT
if (mp_obj_is_str(arg)) {

View File

@ -11,7 +11,7 @@
#include "py/objtuple.h"
#include "py/binary.h"
#include "supervisor/shared/translate.h"
#include "supervisor/shared/translate/translate.h"
#if MICROPY_PY_UCTYPES

View File

@ -8,7 +8,7 @@
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
#include "supervisor/shared/translate/translate.h"
#if MICROPY_PY_UHASHLIB

View File

@ -6,7 +6,7 @@
#include "py/objlist.h"
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
#include "supervisor/shared/translate/translate.h"
#if MICROPY_PY_UHEAPQ

View File

@ -13,7 +13,7 @@
#include "py/runtime.h"
#include "py/stream.h"
#include "supervisor/shared/translate.h"
#include "supervisor/shared/translate/translate.h"
#if MICROPY_PY_UJSON

146
extmod/moduplatform.c Normal file
View File

@ -0,0 +1,146 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "py/runtime.h"
#include "py/objtuple.h"
#include "py/objstr.h"
#include "py/mphal.h"
#include "genhdr/mpversion.h"
#if MICROPY_PY_UPLATFORM
// platform - Access to underlying platform's identifying data
// TODO: Add more architectures, compilers and libraries.
// See: https://sourceforge.net/p/predef/wiki/Home/
#if defined(__ARM_ARCH)
#define PLATFORM_ARCH "arm"
#elif defined(__x86_64__) || defined(_WIN64)
#define PLATFORM_ARCH "x86_64"
#elif defined(__i386__) || defined(_M_IX86)
#define PLATFORM_ARCH "x86"
#elif defined(__xtensa__) || defined(_M_IX86)
#define PLATFORM_ARCH "xtensa"
#else
#define PLATFORM_ARCH ""
#endif
#if defined(__GNUC__)
#define PLATFORM_COMPILER \
"GCC " \
MP_STRINGIFY(__GNUC__) "." \
MP_STRINGIFY(__GNUC_MINOR__) "." \
MP_STRINGIFY(__GNUC_PATCHLEVEL__)
#elif defined(__ARMCC_VERSION)
#define PLATFORM_COMPILER \
"ARMCC " \
MP_STRINGIFY((__ARMCC_VERSION / 1000000)) "." \
MP_STRINGIFY((__ARMCC_VERSION / 10000 % 100)) "." \
MP_STRINGIFY((__ARMCC_VERSION % 10000))
#elif defined(_MSC_VER)
#if defined(_WIN64)
#define COMPILER_BITS "64 bit"
#elif defined(_M_IX86)
#define COMPILER_BITS "32 bit"
#else
#define COMPILER_BITS ""
#endif
#define PLATFORM_COMPILER \
"MSC v." MP_STRINGIFY(_MSC_VER) " " COMPILER_BITS
#else
#define PLATFORM_COMPILER ""
#endif
#if defined(__GLIBC__)
#define PLATFORM_LIBC_LIB "glibc"
#define PLATFORM_LIBC_VER \
MP_STRINGIFY(__GLIBC__) "." \
MP_STRINGIFY(__GLIBC_MINOR__)
#elif defined(__NEWLIB__)
#define PLATFORM_LIBC_LIB "newlib"
#define PLATFORM_LIBC_VER _NEWLIB_VERSION
#else
#define PLATFORM_LIBC_LIB ""
#define PLATFORM_LIBC_VER ""
#endif
#if defined(__linux)
#define PLATFORM_SYSTEM "Linux"
#elif defined(__unix__)
#define PLATFORM_SYSTEM "Unix"
#elif defined(__CYGWIN__)
#define PLATFORM_SYSTEM "Cygwin"
#elif defined(_WIN32)
#define PLATFORM_SYSTEM "Windows"
#else
#define PLATFORM_SYSTEM "MicroPython"
#endif
#ifndef MICROPY_PLATFORM_VERSION
#define MICROPY_PLATFORM_VERSION ""
#endif
STATIC const MP_DEFINE_STR_OBJ(info_platform_obj, PLATFORM_SYSTEM "-" MICROPY_VERSION_STRING "-" \
PLATFORM_ARCH "-" MICROPY_PLATFORM_VERSION "-with-" PLATFORM_LIBC_LIB "" PLATFORM_LIBC_VER);
STATIC const MP_DEFINE_STR_OBJ(info_python_compiler_obj, PLATFORM_COMPILER);
STATIC const MP_DEFINE_STR_OBJ(info_libc_lib_obj, PLATFORM_LIBC_LIB);
STATIC const MP_DEFINE_STR_OBJ(info_libc_ver_obj, PLATFORM_LIBC_VER);
STATIC const mp_rom_obj_tuple_t info_libc_tuple_obj = {
{&mp_type_tuple}, 2, {MP_ROM_PTR(&info_libc_lib_obj), MP_ROM_PTR(&info_libc_ver_obj)}
};
STATIC mp_obj_t platform_platform(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
return MP_OBJ_FROM_PTR(&info_platform_obj);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(platform_platform_obj, 0, platform_platform);
STATIC mp_obj_t platform_python_compiler(void) {
return MP_OBJ_FROM_PTR(&info_python_compiler_obj);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(platform_python_compiler_obj, platform_python_compiler);
STATIC mp_obj_t platform_libc_ver(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
return MP_OBJ_FROM_PTR(&info_libc_tuple_obj);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(platform_libc_ver_obj, 0, platform_libc_ver);
STATIC const mp_rom_map_elem_t modplatform_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uplatform) },
{ MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&platform_platform_obj) },
{ MP_ROM_QSTR(MP_QSTR_python_compiler), MP_ROM_PTR(&platform_python_compiler_obj) },
{ MP_ROM_QSTR(MP_QSTR_libc_ver), MP_ROM_PTR(&platform_libc_ver_obj) },
};
STATIC MP_DEFINE_CONST_DICT(modplatform_globals, modplatform_globals_table);
const mp_obj_module_t mp_module_uplatform = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&modplatform_globals,
};
#endif // MICROPY_PY_UPLATFORM

View File

@ -477,11 +477,16 @@ MP_REGISTER_MODULE(MP_QSTR_re, mp_module_ure, MICROPY_PY_URE);
// only if module is enabled by config setting.
#define re1_5_fatal(x) assert(!x)
#include "lib/re1.5/compilecode.c"
#if MICROPY_PY_URE_DEBUG
#include "lib/re1.5/dumpcode.c"
#endif
#include "lib/re1.5/recursiveloop.c"
#include "lib/re1.5/charclass.c"
#if MICROPY_PY_URE_DEBUG
// Make sure the output print statements go to the same output as other Python output.
#define printf(...) mp_printf(&mp_plat_print, __VA_ARGS__)
#include "lib/re1.5/dumpcode.c"
#undef printf
#endif
#endif // MICROPY_PY_URE

View File

@ -9,13 +9,14 @@
#include <stdio.h>
#include "py/ioctl.h"
#include "py/stream.h"
#include "py/runtime.h"
#include "py/obj.h"
#include "py/objlist.h"
#include "py/stream.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "shared/runtime/interrupt_char.h"
// Flags for poll()
#define FLAG_ONESHOT (1)
@ -230,6 +231,9 @@ STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) {
break;
}
RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
return 0;
}
}
return n_ready;

View File

@ -10,7 +10,7 @@
#include "py/runtime.h"
#include "py/smallint.h"
#include "supervisor/shared/translate.h"
#include "supervisor/shared/translate/translate.h"
#if MICROPY_PY_UTIMEQ

View File

@ -10,7 +10,7 @@
#include "py/stream.h"
#include "py/mperrno.h"
#include "supervisor/shared/translate.h"
#include "supervisor/shared/translate/translate.h"
#if MICROPY_PY_UZLIB
@ -114,12 +114,12 @@ STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
#endif
#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_stream_p_t decompio_stream_p = {
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = decompio_read,
};
#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_obj_type_t decompio_type = {
{ &mp_type_type },
.flags = MP_TYPE_FLAG_EXTENDED,

View File

@ -36,7 +36,7 @@ class SingletonGenerator:
self.state = None
self.exc = StopIteration()
def __iter__(self):
def __await__(self):
return self
def __next__(self):

View File

@ -66,7 +66,7 @@ async def gather(*aws, return_exceptions=False):
# # cancel all waiting tasks
# raise er
ts[i] = await ts[i]
except Exception as er:
except (core.CancelledError, Exception) as er:
if return_exceptions:
ts[i] = er
else:

View File

@ -130,7 +130,7 @@ class Task:
self.ph_next = None # Paring heap
self.ph_rightmost_parent = None # Paring heap
def __iter__(self):
def __await__(self):
if not self.state:
# Task finished, signal that is has been await'ed on.
self.state = False
@ -141,8 +141,12 @@ class Task:
def __next__(self):
if not self.state:
# Task finished, raise return value to caller so it can continue.
raise self.data
if self.data is None:
# Task finished but has already been sent to the loop's exception handler.
raise StopIteration
else:
# Task finished, raise return value to caller so it can continue.
raise self.data
else:
# Put calling task on waiting queue.
self.state.push_head(core.cur_task)

@ -1 +1 @@
Subproject commit 0c7c6b88f3ec1b1d11d2f7d8b185e28ac657c06d
Subproject commit 25a825e41c26cfcee018b762416741d0d63aeabf

View File

@ -20,7 +20,7 @@
#include "extmod/vfs_fat.h"
#include "shared/timeutils/timeutils.h"
#include "supervisor/filesystem.h"
#include "supervisor/shared/translate.h"
#include "supervisor/shared/translate/translate.h"
#if FF_MAX_SS == FF_MIN_SS
#define SECSIZE(fs) (FF_MIN_SS)
@ -30,6 +30,11 @@
#define mp_obj_fat_vfs_t fs_user_mount_t
// Factoring this common call saves about 90 bytes.
STATIC NORETURN void mp_raise_OSError_fresult(FRESULT res) {
mp_raise_OSError(fresult_to_errno_table[res]);
}
STATIC mp_import_stat_t fat_vfs_import_stat(void *vfs_in, const char *path) {
fs_user_mount_t *vfs = vfs_in;
FILINFO fno;
@ -64,7 +69,7 @@ STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_
// don't error out if no filesystem, to let mkfs()/mount() create one if wanted
vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NO_FILESYSTEM;
} else if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
mp_raise_OSError_fresult(res);
}
return MP_OBJ_FROM_PTR(vfs);
@ -97,7 +102,7 @@ STATIC mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) {
res = f_mkfs(&vfs->fatfs, FM_FAT32, 0, working_buf, sizeof(working_buf));
}
if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
mp_raise_OSError_fresult(res);
}
return mp_const_none;
@ -172,7 +177,7 @@ STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) {
iter->is_str = is_str_type;
FRESULT res = f_opendir(&self->fatfs, &iter->dir, path);
if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
mp_raise_OSError_fresult(res);
}
return MP_OBJ_FROM_PTR(iter);
@ -188,7 +193,7 @@ STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t vfs_in, mp_obj_t path_in, mp_in
FRESULT res = f_stat(&self->fatfs, path, &fno);
if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
mp_raise_OSError_fresult(res);
}
// check if path is a file or directory
@ -196,7 +201,7 @@ STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t vfs_in, mp_obj_t path_in, mp_in
res = f_unlink(&self->fatfs, path);
if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
mp_raise_OSError_fresult(res);
}
return mp_const_none;
} else {
@ -220,22 +225,7 @@ STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_
const char *old_path = mp_obj_str_get_str(path_in);
const char *new_path = mp_obj_str_get_str(path_out);
// Check to see if we're moving a directory into itself. This occurs when we're moving a
// directory where the old path is a prefix of the new and the next character is a "/" and thus
// preserves the original directory name.
FILINFO fno;
FRESULT res = f_stat(&self->fatfs, old_path, &fno);
if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
}
if ((fno.fattrib & AM_DIR) != 0 &&
strlen(new_path) > strlen(old_path) &&
new_path[strlen(old_path)] == '/' &&
strncmp(old_path, new_path, strlen(old_path)) == 0) {
mp_raise_OSError(MP_EINVAL);
}
res = f_rename(&self->fatfs, old_path, new_path);
FRESULT res = f_rename(&self->fatfs, old_path, new_path);
if (res == FR_EXIST) {
// if new_path exists then try removing it (but only if it's a file)
fat_vfs_remove_internal(vfs_in, path_out, 0); // 0 == file attribute
@ -245,7 +235,7 @@ STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_
if (res == FR_OK) {
return mp_const_none;
} else {
mp_raise_OSError(fresult_to_errno_table[res]);
mp_raise_OSError_fresult(res);
}
}
@ -259,7 +249,7 @@ STATIC mp_obj_t fat_vfs_mkdir(mp_obj_t vfs_in, mp_obj_t path_o) {
if (res == FR_OK) {
return mp_const_none;
} else {
mp_raise_OSError(fresult_to_errno_table[res]);
mp_raise_OSError_fresult(res);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_mkdir_obj, fat_vfs_mkdir);
@ -273,7 +263,7 @@ STATIC mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) {
FRESULT res = f_chdir(&self->fatfs, path);
if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
mp_raise_OSError_fresult(res);
}
return mp_const_none;
@ -286,7 +276,7 @@ STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) {
char buf[MICROPY_ALLOC_PATH_MAX + 1];
FRESULT res = f_getcwd(&self->fatfs, buf, sizeof(buf));
if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
mp_raise_OSError_fresult(res);
}
return mp_obj_new_str(buf, strlen(buf));
}
@ -307,7 +297,7 @@ STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
} else {
FRESULT res = f_stat(&self->fatfs, path, &fno);
if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
mp_raise_OSError_fresult(res);
}
}
@ -357,7 +347,7 @@ STATIC mp_obj_t fat_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) {
FATFS *fatfs = &self->fatfs;
FRESULT res = f_getfree(fatfs, &nclst);
if (FR_OK != res) {
mp_raise_OSError(fresult_to_errno_table[res]);
mp_raise_OSError_fresult(res);
}
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
@ -395,7 +385,7 @@ STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs
res = f_mkfs(&self->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf));
}
if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
mp_raise_OSError_fresult(res);
}
self->blockdev.flags &= ~MP_BLOCKDEV_FLAG_NO_FILESYSTEM;
@ -410,13 +400,42 @@ STATIC mp_obj_t vfs_fat_umount(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, vfs_fat_umount);
STATIC mp_obj_t vfs_fat_utime(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t times_in) {
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);
const char *path = mp_obj_str_get_str(path_in);
if (!mp_obj_is_tuple_compatible(times_in)) {
mp_raise_type_arg(&mp_type_TypeError, times_in);
}
mp_obj_t *otimes;
mp_obj_get_array_fixed_n(times_in, 2, &otimes);
// Validate that both elements of the tuple are int and discard the second one
int time[2];
time[0] = mp_obj_get_int(otimes[0]);
time[1] = mp_obj_get_int(otimes[1]);
timeutils_struct_time_t tm;
timeutils_seconds_since_epoch_to_struct_time(time[0], &tm);
FILINFO fno;
fno.fdate = (WORD)(((tm.tm_year - 1980) * 512U) | tm.tm_mon * 32U | tm.tm_mday);
fno.ftime = (WORD)(tm.tm_hour * 2048U | tm.tm_min * 32U | tm.tm_sec / 2U);
FRESULT res = f_utime(&self->fatfs, path, &fno);
if (res != FR_OK) {
mp_raise_OSError_fresult(res);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_utime_obj, vfs_fat_utime);
#if MICROPY_FATFS_USE_LABEL
STATIC mp_obj_t vfs_fat_getlabel(mp_obj_t self_in) {
fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in);
char working_buf[12];
FRESULT res = f_getlabel(&self->fatfs, working_buf, NULL);
if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
mp_raise_OSError_fresult(res);
}
return mp_obj_new_str(working_buf, strlen(working_buf));
}
@ -431,7 +450,7 @@ STATIC mp_obj_t vfs_fat_setlabel(mp_obj_t self_in, mp_obj_t label_in) {
if (res == FR_WRITE_PROTECTED) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Read-only filesystem"));
}
mp_raise_OSError(fresult_to_errno_table[res]);
mp_raise_OSError_fresult(res);
}
return mp_const_none;
}
@ -440,7 +459,7 @@ STATIC const mp_obj_property_t fat_vfs_label_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&fat_vfs_getlabel_obj,
(mp_obj_t)&fat_vfs_setlabel_obj,
(mp_obj_t)MP_ROM_NONE},
MP_ROM_NONE},
};
#endif
@ -461,6 +480,7 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&fat_vfs_statvfs_obj) },
{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_fat_mount_obj) },
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&fat_vfs_umount_obj) },
{ MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&fat_vfs_utime_obj) },
#if MICROPY_FATFS_USE_LABEL
{ MP_ROM_QSTR(MP_QSTR_label), MP_ROM_PTR(&fat_vfs_label_obj) },
#endif

View File

@ -182,7 +182,7 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar
}
if (rwxa_count != 1 || plus_count > 1 || bt_count > 1 || bad_mode) {
mp_raise_ValueError(translate("Invalid mode"));
mp_arg_error_invalid(MP_QSTR_mode);
}
assert(vfs != NULL);

View File

@ -8,7 +8,7 @@
#include "py/runtime.h"
#include "py/stream.h"
#include "extmod/vfs_posix.h"
#include "supervisor/shared/translate.h"
#include "supervisor/shared/translate/translate.h"
#if (defined(MICROPY_VFS_POSIX) && MICROPY_VFS_POSIX) || (defined(MICROPY_VFS_POSIX_FILE) && MICROPY_VFS_POSIX_FILE)
@ -17,6 +17,8 @@
#ifdef _WIN32
#define fsync _commit
#else
#include <poll.h>
#endif
typedef struct _mp_obj_vfs_posix_file_t {
@ -180,6 +182,32 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_
return 0;
case MP_STREAM_GET_FILENO:
return o->fd;
#if MICROPY_PY_USELECT
case MP_STREAM_POLL: {
#ifdef _WIN32
mp_raise_NotImplementedError(MP_ERROR_TEXT("poll on file not available on win32"));
#else
mp_uint_t ret = 0;
uint8_t pollevents = 0;
if (arg & MP_STREAM_POLL_RD) {
pollevents |= POLLIN;
}
if (arg & MP_STREAM_POLL_WR) {
pollevents |= POLLOUT;
}
struct pollfd pfd = { .fd = o->fd, .events = pollevents };
if (poll(&pfd, 1, 0) > 0) {
if (pfd.revents & POLLIN) {
ret |= MP_STREAM_POLL_RD;
}
if (pfd.revents & POLLOUT) {
ret |= MP_STREAM_POLL_WR;
}
}
return ret;
#endif
}
#endif
default:
*errcode = EINVAL;
return MP_STREAM_ERROR;

@ -1 +1 @@
Subproject commit c55da0dee66302d2fa8ed31623d047c307f409b2
Subproject commit ba05423ed9aae09ce293603b519a4ac644ef0dab

@ -1 +1 @@
Subproject commit a695cde1b1cc957bcd10875b12ae82d1deeb0157
Subproject commit 4fd499e39720f8ce970cceeb97c2a85c485f7335

@ -1 +1 @@
Subproject commit c24a5310bc259cd9d93b1f42468e07f41d4b0e56
Subproject commit b06b47037aed97475b1676b104d1f4b05c3f5e86

@ -1 +1 @@
Subproject commit 169715b3444c614e55827ccf79b35b2b5e11f1d2
Subproject commit 9ace770b048be9ab0da4a154af279dbb643bbdb0

@ -1 +1 @@
Subproject commit 2017afdfb43d3d9c5a73f8e85e951a583b18206a
Subproject commit 47f848f13f75d2f62d16407edaaf6dd0ec1fc3cc

@ -1 +1 @@
Subproject commit 8d09b29a1a92499dbbd10dd832f27db71057af5f
Subproject commit a37c7cc83685f2ff84a171a519207567a75d0947

@ -1 +1 @@
Subproject commit 8a6ab89b7d19f45a20b3f794cf900e23c9a8453b
Subproject commit 4a4619a524918f2705c05ca4959385937afa9a7c

@ -1 +1 @@
Subproject commit 4fc5a32763c4a6eac3a9446e296a9e925cc29a5c
Subproject commit 726270f5103d9d94810eb8b52041b7521afafc5c

@ -1 +1 @@
Subproject commit 993bd12e1747ec117e8d104a5e9f4659c8a347a3
Subproject commit 656be4d79196b5f25ab9ebca731d448c5b3bdc17

@ -1 +1 @@
Subproject commit 0ec87891f9a28ee3c5ae3b020b60d361684f466d
Subproject commit 6cf9f3cf32e0c176c861de6356813ea4d08034d6

@ -1 +1 @@
Subproject commit e07090117766d4a9ea2de07cd6f5418990cc598b
Subproject commit d645fc2aded3606e5b0c17689e9f29e7e56bb612

@ -1 +1 @@
Subproject commit de4829a027a45882ae5477e50a75985e0e59f759
Subproject commit ee6bfcf9e676eb435c8890db37f07719984a60a1

@ -0,0 +1 @@
Subproject commit 8eedf860beca0d32219189b72ea6fc8eea7e66db

@ -1 +1 @@
Subproject commit 68744ede79c992a3df8322c21a1468c5ccaef2ee
Subproject commit 3d7d404a1cafc02f6c3391b100157490132e5c5f

@ -1 +1 @@
Subproject commit d79dd180cf6062e97d6a12cbc8dc7fdbedcc752b
Subproject commit 93c7e0ed55e7ed011908ac9a1c0f8228f0f4323b

@ -1 +1 @@
Subproject commit 2ca37f927b3ee3aad379c2991f36b3ef1be0203d
Subproject commit 992b601e2469f30e95ec35c9859b4aa2cd917504

@ -0,0 +1 @@
Subproject commit 794488d1de3d17d1a08887c4a651cfac2c5a1524

@ -1 +1 @@
Subproject commit 8fc5eaecb3e24e4109bcc788f41461f1c45c3719
Subproject commit 1919916dcf57e0879832b9c274c5fb77712d7775

@ -1 +1 @@
Subproject commit ebbe69667d53ae76bc6d82e5296f87520ffbb5ae
Subproject commit 5b4703428fc299ac268d08350c885122b2af1e75

@ -1 +1 @@
Subproject commit f94ef67425516f23c889d217ffe5a3a710c1d278
Subproject commit c8e82b96c68041a11a52f3053d0d2733ae2d1a49

@ -1 +1 @@
Subproject commit 1127e3f7bcefa9fddb5b7f30533ecc6c58b420ea
Subproject commit b6891e734183f978e7b3d0a363140e98635c0a04

@ -1 +1 @@
Subproject commit 9995c45a5ed1d455a4a8b7bfb9eb134de7f2b9db
Subproject commit 31c819f377cf71f61cfb84eae159f1f948980db7

@ -1 +1 @@
Subproject commit 9ca3bf00c6a2dd1de2d315a3b952a381d720aa7d
Subproject commit 1064fdee5a1421f528af452be5e45ae95ef2b89a

@ -0,0 +1 @@
Subproject commit 7eeea1aaf6bb5fa0deb080a1dc1aa3cd103f9aad

@ -1 +1 @@
Subproject commit 4ac43288938abb4c3db127eeb79ef0d4ea4c16ea
Subproject commit cad34af5267aca3665fdaf1ea5a0eee921d13f06

@ -1 +1 @@
Subproject commit 9ac490905834466319279a3390c914f1fd83733f
Subproject commit 96b4a05c8a225ad7ddc392be7fb69efebe151981

@ -1 +1 @@
Subproject commit 0df4521b4a04ca1236960ff889ede118ec4305b5
Subproject commit df4c73a5e719f17fae0309e811ff17627cd0f268

@ -1 +1 @@
Subproject commit 79678c6adb2252de8fed6273604bc6ac676132a5
Subproject commit f611d5e31c9735a3c3ac43185e35dcd5f659e3aa

@ -1 +1 @@
Subproject commit 900b28cbae008e3253c4c40496e49faea9fb7034
Subproject commit 317f4bdb799afa59b164def4ea0610f57db9922e

@ -1 +1 @@
Subproject commit b7a76420d1dec119f8744aa7c0ea500e235561d1
Subproject commit bb2fc8c157ee44869cde4cbc1ab20e6f31ac727f

@ -0,0 +1 @@
Subproject commit 168624262c18f5ee80ec392c0844d6a4c6548760

@ -1 +1 @@
Subproject commit c5b480434de8fa56d8ba978a57cd3919fdc9da2a
Subproject commit 9ff56ce53f05e23ff678965ba54af89b24b1199a

@ -1 +1 @@
Subproject commit ca56187fe7af315130808191b004432fdfdc1b09
Subproject commit 0a8fcbfc92060eb298ea52d5e88587b37347a0be

@ -1 +1 @@
Subproject commit 755784b6acc8ba419a085bee2d2dc4374f0d0030
Subproject commit dc605bb22914d77d80c5342cbb4c10f773aede95

@ -1 +1 @@
Subproject commit d4ac6ce3eea2c87781fa2df4e431d9440c610fad
Subproject commit 43a4f15d604919d6e143e975a85abf7b96a4061d

@ -0,0 +1 @@
Subproject commit 7832bbb5449d55d8c7b731e4ff7490b801e94a9e

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