Merge remote-tracking branch 'origin/main' into q-and-d-uvc

This commit is contained in:
Jeff Epler 2024-01-31 08:27:13 -06:00
commit 1c95a85ceb
115 changed files with 1989 additions and 695 deletions

View file

@ -16,7 +16,7 @@ runs:
tar -xaf dosfstools-4.2.tar.gz tar -xaf dosfstools-4.2.tar.gz
cd dosfstools-4.2 cd dosfstools-4.2
./configure ./configure
make -j 2 make -j4
cd src cd src
echo >> $GITHUB_PATH $(pwd) echo >> $GITHUB_PATH $(pwd)
shell: bash shell: bash

View file

@ -18,7 +18,7 @@ runs:
shell: bash shell: bash
- name: Cache IDF submodules - name: Cache IDF submodules
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: | path: |
.git/modules/ports/espressif/esp-idf .git/modules/ports/espressif/esp-idf
@ -26,7 +26,7 @@ runs:
key: submodules-idf-${{ steps.idf-commit.outputs.commit }} key: submodules-idf-${{ steps.idf-commit.outputs.commit }}
- name: Cache IDF tools - name: Cache IDF tools
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: ${{ env.IDF_TOOLS_PATH }} path: ${{ env.IDF_TOOLS_PATH }}
key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-idf-${{ steps.idf-commit.outputs.commit }} key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-idf-${{ steps.idf-commit.outputs.commit }}

View file

@ -16,7 +16,7 @@ runs:
- name: Cache python dependencies - name: Cache python dependencies
id: cache-python-deps id: cache-python-deps
if: inputs.action == 'cache' if: inputs.action == 'cache'
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: .cp_tools path: .cp_tools
key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-cp-${{ hashFiles('requirements-dev.txt') }} key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-cp-${{ hashFiles('requirements-dev.txt') }}
@ -24,7 +24,7 @@ runs:
- name: Restore python dependencies - name: Restore python dependencies
id: restore-python-deps id: restore-python-deps
if: inputs.action == 'restore' if: inputs.action == 'restore'
uses: actions/cache/restore@v3 uses: actions/cache/restore@v4
with: with:
path: .cp_tools path: .cp_tools
key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-cp-${{ hashFiles('requirements-dev.txt') }} key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-cp-${{ hashFiles('requirements-dev.txt') }}

View file

@ -48,7 +48,7 @@ runs:
- name: Cache submodules - name: Cache submodules
if: ${{ inputs.action == 'cache' }} if: ${{ inputs.action == 'cache' }}
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: ".git/modules/\n${{ join(fromJSON(steps.create-submodule-status.outputs.submodules), '\n') }}" path: ".git/modules/\n${{ join(fromJSON(steps.create-submodule-status.outputs.submodules), '\n') }}"
key: submodules-common-${{ hashFiles('submodule_status') }} key: submodules-common-${{ hashFiles('submodule_status') }}
@ -56,7 +56,7 @@ runs:
- name: Restore submodules - name: Restore submodules
if: ${{ inputs.action == 'restore' }} if: ${{ inputs.action == 'restore' }}
uses: actions/cache/restore@v3 uses: actions/cache/restore@v4
with: with:
path: ".git/modules/\n${{ join(fromJSON(steps.create-submodule-status.outputs.submodules), '\n') }}" path: ".git/modules/\n${{ join(fromJSON(steps.create-submodule-status.outputs.submodules), '\n') }}"
key: submodules-common-${{ hashFiles('submodule_status') }} key: submodules-common-${{ hashFiles('submodule_status') }}

View file

@ -16,7 +16,7 @@ runs:
id: download-mpy-cross id: download-mpy-cross
if: inputs.download == 'true' if: inputs.download == 'true'
continue-on-error: true continue-on-error: true
uses: actions/download-artifact@v3 uses: actions/download-artifact@v4
with: with:
name: mpy-cross name: mpy-cross
path: mpy-cross/build path: mpy-cross/build
@ -28,7 +28,7 @@ runs:
- name: Build mpy-cross - name: Build mpy-cross
if: inputs.download == 'false' || steps.download-mpy-cross.outcome == 'failure' if: inputs.download == 'false' || steps.download-mpy-cross.outcome == 'failure'
run: make -C mpy-cross -j2 run: make -C mpy-cross -j4
shell: bash shell: bash
env: env:
CP_VERSION: ${{ inputs.cp-version }} CP_VERSION: ${{ inputs.cp-version }}
@ -36,7 +36,7 @@ runs:
- name: Upload mpy-cross - name: Upload mpy-cross
if: inputs.download == 'false' || steps.download-mpy-cross.outcome == 'failure' if: inputs.download == 'false' || steps.download-mpy-cross.outcome == 'failure'
continue-on-error: true continue-on-error: true
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: mpy-cross name: mpy-cross
path: mpy-cross/build/mpy-cross path: mpy-cross/build/mpy-cross

View file

@ -26,12 +26,13 @@ jobs:
board: ${{ fromJSON(inputs.boards) }} board: ${{ fromJSON(inputs.boards) }}
steps: steps:
- name: Set up repository - name: Set up repository
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: false submodules: false
show-progress: false
fetch-depth: 1 fetch-depth: 1
- name: Set up python - name: Set up python
uses: actions/setup-python@v4 uses: actions/setup-python@v5
with: with:
python-version: 3.x python-version: 3.x
- name: Set up port - name: Set up port
@ -75,7 +76,7 @@ jobs:
PULL: ${{ github.event.number }} PULL: ${{ github.event.number }}
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: ${{ matrix.board }} name: ${{ matrix.board }}
path: bin/${{ matrix.board }} path: bin/${{ matrix.board }}

View file

@ -28,12 +28,13 @@ jobs:
OS_static-raspbian: linux-raspbian OS_static-raspbian: linux-raspbian
steps: steps:
- name: Set up repository - name: Set up repository
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: false submodules: false
show-progress: false
fetch-depth: 1 fetch-depth: 1
- name: Set up python - name: Set up python
uses: actions/setup-python@v4 uses: actions/setup-python@v5
with: with:
python-version: 3.x python-version: 3.x
- name: Set up submodules - name: Set up submodules
@ -53,7 +54,7 @@ jobs:
sudo apt-get install -y mingw-w64 sudo apt-get install -y mingw-w64
- name: Build mpy-cross.${{ matrix.mpy-cross }} - name: Build mpy-cross.${{ matrix.mpy-cross }}
run: make -C mpy-cross -j2 -f Makefile.${{ matrix.mpy-cross }} run: make -C mpy-cross -j4 -f Makefile.${{ matrix.mpy-cross }}
- name: Set output - name: Set output
run: | run: |
@ -61,7 +62,7 @@ jobs:
echo >> $GITHUB_ENV "OS=${{ env[format('OS_{0}', matrix.mpy-cross)] }}" echo >> $GITHUB_ENV "OS=${{ env[format('OS_{0}', matrix.mpy-cross)] }}"
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: mpy-cross.${{ env.EX }} name: mpy-cross.${{ env.EX }}
path: mpy-cross/build-${{ matrix.mpy-cross }}/mpy-cross.${{ env.EX }} path: mpy-cross/build-${{ matrix.mpy-cross }}/mpy-cross.${{ env.EX }}

View file

@ -28,12 +28,13 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
- name: Set up repository - name: Set up repository
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: false submodules: false
show-progress: false
fetch-depth: 1 fetch-depth: 1
- name: Set up python - name: Set up python
uses: actions/setup-python@v4 uses: actions/setup-python@v5
with: with:
python-version: 3.x python-version: 3.x
- name: Duplicate USB VID/PID check - name: Duplicate USB VID/PID check
@ -108,12 +109,13 @@ jobs:
CP_VERSION: ${{ needs.scheduler.outputs.cp-version }} CP_VERSION: ${{ needs.scheduler.outputs.cp-version }}
steps: steps:
- name: Set up repository - name: Set up repository
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: false submodules: false
show-progress: false
fetch-depth: 1 fetch-depth: 1
- name: Set up python - name: Set up python
uses: actions/setup-python@v4 uses: actions/setup-python@v5
with: with:
python-version: 3.x python-version: 3.x
- name: Set up submodules - name: Set up submodules
@ -124,21 +126,21 @@ jobs:
python3 --version python3 --version
msgfmt --version msgfmt --version
- name: Build mpy-cross - name: Build mpy-cross
run: make -C mpy-cross -j2 run: make -C mpy-cross -j4
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v4
with: with:
name: mpy-cross-macos-11-x64 name: mpy-cross-macos-11-x64
path: mpy-cross/build/mpy-cross path: mpy-cross/build/mpy-cross
- name: Build mpy-cross (arm64) - name: Build mpy-cross (arm64)
run: make -C mpy-cross -j2 -f Makefile.m1 V=2 run: make -C mpy-cross -j4 -f Makefile.m1 V=2
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v4
with: with:
name: mpy-cross-macos-11-arm64 name: mpy-cross-macos-11-arm64
path: mpy-cross/build-arm64/mpy-cross-arm64 path: mpy-cross/build-arm64/mpy-cross-arm64
- name: Make universal binary - name: Make universal binary
run: lipo -create -output mpy-cross-macos-universal mpy-cross/build/mpy-cross mpy-cross/build-arm64/mpy-cross-arm64 run: lipo -create -output mpy-cross-macos-universal mpy-cross/build/mpy-cross mpy-cross/build-arm64/mpy-cross-arm64
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: mpy-cross-macos-11-universal name: mpy-cross-macos-11-universal
path: mpy-cross-macos-universal path: mpy-cross-macos-universal
@ -163,12 +165,13 @@ jobs:
CP_VERSION: ${{ needs.scheduler.outputs.cp-version }} CP_VERSION: ${{ needs.scheduler.outputs.cp-version }}
steps: steps:
- name: Set up repository - name: Set up repository
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: false submodules: false
show-progress: false
fetch-depth: 1 fetch-depth: 1
- name: Set up python - name: Set up python
uses: actions/setup-python@v4 uses: actions/setup-python@v5
with: with:
python-version: 3.x python-version: 3.x
- name: Set up submodules - name: Set up submodules
@ -179,23 +182,23 @@ jobs:
sudo apt-get install -y latexmk librsvg2-bin texlive-fonts-recommended texlive-latex-recommended texlive-latex-extra sudo apt-get install -y latexmk librsvg2-bin texlive-fonts-recommended texlive-latex-recommended texlive-latex-extra
pip install -r requirements-doc.txt pip install -r requirements-doc.txt
- name: Build and Validate Stubs - name: Build and Validate Stubs
run: make check-stubs -j2 run: make check-stubs -j4
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v4
with: with:
name: stubs name: stubs
path: circuitpython-stubs/dist/* path: circuitpython-stubs/dist/*
- name: Test Documentation Build (HTML) - name: Test Documentation Build (HTML)
run: sphinx-build -E -W -b html -D version=${{ env.CP_VERSION }} -D release=${{ env.CP_VERSION }} . _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@v3 - uses: actions/upload-artifact@v4
with: with:
name: docs name: docs-html
path: _build/html path: _build/html
- name: Test Documentation Build (LaTeX/PDF) - name: Test Documentation Build (LaTeX/PDF)
run: | run: |
make latexpdf make latexpdf
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v4
with: with:
name: docs name: docs-latexpdf
path: _build/latex path: _build/latex
- name: Upload to S3 - name: Upload to S3
uses: ./.github/actions/upload_aws uses: ./.github/actions/upload_aws
@ -260,24 +263,25 @@ jobs:
which python; python --version; python -c "import cascadetoml" which python; python --version; python -c "import cascadetoml"
which python3; python3 --version; python3 -c "import cascadetoml" which python3; python3 --version; python3 -c "import cascadetoml"
- name: Set up repository - name: Set up repository
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: false submodules: false
show-progress: false
fetch-depth: 1 fetch-depth: 1
- name: Set up submodules - name: Set up submodules
uses: ./.github/actions/deps/submodules uses: ./.github/actions/deps/submodules
- name: build mpy-cross - name: build mpy-cross
run: make -j2 -C mpy-cross run: make -j4 -C mpy-cross
- name: build rp2040 - name: build rp2040
run: make -j2 -C ports/raspberrypi BOARD=adafruit_feather_rp2040 TRANSLATION=de_DE run: make -j4 -C ports/raspberrypi BOARD=adafruit_feather_rp2040 TRANSLATION=de_DE
- name: build samd21 - name: build samd21
run: make -j2 -C ports/atmel-samd BOARD=feather_m0_express TRANSLATION=zh_Latn_pinyin run: make -j4 -C ports/atmel-samd BOARD=feather_m0_express TRANSLATION=zh_Latn_pinyin
- name: build samd51 - name: build samd51
run: make -j2 -C ports/atmel-samd BOARD=feather_m4_express TRANSLATION=es run: make -j4 -C ports/atmel-samd BOARD=feather_m4_express TRANSLATION=es
- name: build nrf - name: build nrf
run: make -j2 -C ports/nrf BOARD=feather_nrf52840_express TRANSLATION=fr run: make -j4 -C ports/nrf BOARD=feather_nrf52840_express TRANSLATION=fr
- name: build stm - name: build stm
run: make -j2 -C ports/stm BOARD=feather_stm32f405_express TRANSLATION=pt_BR run: make -j4 -C ports/stm BOARD=feather_stm32f405_express TRANSLATION=pt_BR
# I gave up trying to do esp builds on windows when I saw # I gave up trying to do esp builds on windows when I saw
# ERROR: Platform MINGW64_NT-10.0-17763-x86_64 appears to be unsupported # ERROR: Platform MINGW64_NT-10.0-17763-x86_64 appears to be unsupported
# https://github.com/espressif/esp-idf/issues/7062 # https://github.com/espressif/esp-idf/issues/7062

View file

@ -17,12 +17,13 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
- name: Set up repository - name: Set up repository
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: false submodules: false
show-progress: false
fetch-depth: 1 fetch-depth: 1
- name: Set up python - name: Set up python
uses: actions/setup-python@v4 uses: actions/setup-python@v5
with: with:
python-version: 3.x python-version: 3.x
- name: Set up submodules - name: Set up submodules

View file

@ -42,7 +42,7 @@ jobs:
run: | run: |
> custom-build && git add custom-build > custom-build && git add custom-build
- name: Set up python - name: Set up python
uses: actions/setup-python@v4 uses: actions/setup-python@v5
with: with:
python-version: 3.x python-version: 3.x
- name: Set up port - name: Set up port
@ -81,10 +81,10 @@ jobs:
riscv64-unknown-elf-gcc --version || true riscv64-unknown-elf-gcc --version || true
mkfs.fat --version || true mkfs.fat --version || true
- name: Build board - name: Build board
run: make -j2 ${{ inputs.flags }} BOARD=${{ inputs.board }} DEBUG=${{ inputs.debug && '1' || '0' }} TRANSLATION=${{ inputs.language }} run: make -j4 ${{ inputs.flags }} BOARD=${{ inputs.board }} DEBUG=${{ inputs.debug && '1' || '0' }} TRANSLATION=${{ inputs.language }}
working-directory: ports/${{ steps.set-up-port.outputs.port }} working-directory: ports/${{ steps.set-up-port.outputs.port }}
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: ${{ inputs.board }}-${{ inputs.language }}-${{ inputs.version }}${{ inputs.flags != '' && '-custom' || '' }}${{ inputs.debug && '-debug' || '' }} name: ${{ inputs.board }}-${{ inputs.language }}-${{ inputs.version }}${{ inputs.flags != '' && '-custom' || '' }}${{ inputs.debug && '-debug' || '' }}
path: ports/${{ steps.set-up-port.outputs.port }}/build-${{ inputs.board }}/firmware.* path: ports/${{ steps.set-up-port.outputs.port }}/build-${{ inputs.board }}/firmware.*

View file

@ -17,12 +17,13 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Set up repository - name: Set up repository
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: false submodules: false
show-progress: false
fetch-depth: 1 fetch-depth: 1
- name: Set up python - name: Set up python
uses: actions/setup-python@v4 uses: actions/setup-python@v5
with: with:
python-version: 3.x python-version: 3.x
- name: Set up submodules - name: Set up submodules
@ -40,7 +41,7 @@ jobs:
run: git diff > ~/pre-commit.patch run: git diff > ~/pre-commit.patch
- name: Upload patch - name: Upload patch
if: failure() if: failure()
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: patch name: patch
path: ~/pre-commit.patch path: ~/pre-commit.patch

View file

@ -24,12 +24,13 @@ jobs:
TEST_native_mpy: --via-mpy --emit native -d basics float micropython TEST_native_mpy: --via-mpy --emit native -d basics float micropython
steps: steps:
- name: Set up repository - name: Set up repository
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: false submodules: false
show-progress: false
fetch-depth: 1 fetch-depth: 1
- name: Set up python - name: Set up python
uses: actions/setup-python@v4 uses: actions/setup-python@v5
with: with:
python-version: 3.8 python-version: 3.8
- name: Set up submodules - name: Set up submodules
@ -44,12 +45,12 @@ jobs:
with: with:
cp-version: ${{ inputs.cp-version }} cp-version: ${{ inputs.cp-version }}
- name: Build unix port - name: Build unix port
run: make -C ports/unix VARIANT=coverage -j2 run: make -C ports/unix VARIANT=coverage -j4
- name: Run tests - name: Run tests
run: ./run-tests.py -j2 ${{ env[format('TEST_{0}', matrix.test)] }} run: ./run-tests.py -j4 ${{ env[format('TEST_{0}', matrix.test)] }}
working-directory: tests working-directory: tests
- name: Print failure info - name: Print failure info
run: ./run-tests.py -j2 --print-failures run: ./run-tests.py -j4 --print-failures
if: failure() if: failure()
working-directory: tests working-directory: tests
- name: Build native modules - name: Build native modules

View file

@ -52,27 +52,9 @@ SRC_QSTR += $(SRC_C) $(SRC_BINDINGS_EXPANDED) $(STM_SRC_C)
The `Makefile` defines the modules to build and adds the sources to include the `shared-bindings` version and the `common-hal` version within the port specific directory. You may comment out certain subfolders to reduce the number of modules to add but don't comment out individual classes. It won't compile then. The `Makefile` defines the modules to build and adds the sources to include the `shared-bindings` version and the `common-hal` version within the port specific directory. You may comment out certain subfolders to reduce the number of modules to add but don't comment out individual classes. It won't compile then.
### Hooking the modules in ### Hooking the modules in
Built in modules are typically defined in `mpconfigport.h`. To add support you should have something like: Modules are registered by the macro `MP_REGISTER_MODULE` from `py/obj.h`. The macro takes two arguments: the module name as a QSTR and the module object itself. The `board` module is registered like so:
```py
``` MP_REGISTER_MODULE(MP_QSTR_board, board_module);
extern const struct _mp_obj_module_t microcontroller_module;
extern const struct _mp_obj_module_t analogio_module;
extern const struct _mp_obj_module_t digitalio_module;
extern const struct _mp_obj_module_t pulseio_module;
extern const struct _mp_obj_module_t busio_module;
extern const struct _mp_obj_module_t board_module;
extern const struct _mp_obj_module_t time_module;
extern const struct _mp_obj_module_t neopixel_write_module;
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_OBJ_NEW_QSTR(MP_QSTR_microcontroller), (mp_obj_t)&microcontroller_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_analogio), (mp_obj_t)&analogio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_digitalio), (mp_obj_t)&digitalio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_busio), (mp_obj_t)&busio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write),(mp_obj_t)&neopixel_write_module } \
``` ```
### Implementing the Common HAL ### Implementing the Common HAL

View file

@ -173,6 +173,11 @@ def get_settings_from_makefile(port_dir, board_name):
This list must explicitly include any setting queried by tools/ci_set_matrix.py. This list must explicitly include any setting queried by tools/ci_set_matrix.py.
""" """
if os.getenv('NO_BINDINGS_MATRIX'):
return {
'CIRCUITPY_BUILD_EXTENSIONS': '.bin'
}
contents = subprocess.run( contents = subprocess.run(
["make", "-C", port_dir, "-f", "Makefile", f"BOARD={board_name}", "print-CFLAGS", "print-CIRCUITPY_BUILD_EXTENSIONS", "print-FROZEN_MPY_DIRS", "print-SRC_PATTERNS", "print-SRC_SUPERVISOR"], ["make", "-C", port_dir, "-f", "Makefile", f"BOARD={board_name}", "print-CFLAGS", "print-CIRCUITPY_BUILD_EXTENSIONS", "print-FROZEN_MPY_DIRS", "print-SRC_PATTERNS", "print-SRC_SUPERVISOR"],
encoding="utf-8", encoding="utf-8",

View file

@ -165,6 +165,13 @@ Returns a JSON representation of the directory.
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set * `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
* `404 Not Found` - Missing directory * `404 Not Found` - Missing directory
Returns directory information:
* `free`: Count of free blocks on the disk holding this directory.
* `total`: Total blocks that make up the disk holding this directory.
* `block_size`: Size of a block in bytes.
* `writable`: True when CircuitPython and the web workflow can write to the disk. USB may claim a disk instead.
* `files`: Array of objects. One for each file.
Returns information about each file in the directory: Returns information about each file in the directory:
* `name` - File name. No trailing `/` on directory names * `name` - File name. No trailing `/` on directory names
@ -179,7 +186,12 @@ curl -v -u :passw0rd -H "Accept: application/json" -L --location-trusted http://
``` ```
```json ```json
[ {
"free": 451623,
"total": 973344,
"block_size": 32768,
"writable": true,
"files": [
{ {
"name": "world.txt", "name": "world.txt",
"directory": false, "directory": false,
@ -187,6 +199,7 @@ curl -v -u :passw0rd -H "Accept: application/json" -L --location-trusted http://
"file_size": 12 "file_size": 12
} }
] ]
}
``` ```
##### PUT ##### PUT
@ -196,7 +209,7 @@ time resolution) used for the directories modification time. The RTC time will u
Returns: Returns:
* `204 No Content` - Directory exists * `204 No Content` - Directory or file exists
* `201 Created` - Directory created * `201 Created` - Directory created
* `401 Unauthorized` - Incorrect password * `401 Unauthorized` - Incorrect password
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set * `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
@ -373,10 +386,10 @@ curl -v -L http://circuitpython.local/cp/devices.json
Returns information about the attached disk(s). A list of objects, one per disk. Returns information about the attached disk(s). A list of objects, one per disk.
* `root`: Filesystem path to the root of the disk. * `root`: Filesystem path to the root of the disk.
* `free`: Count of free bytes on the disk. * `free`: Count of free blocks on the disk.
* `total`: Total blocks that make up the disk.
* `block_size`: Size of a block in bytes. * `block_size`: Size of a block in bytes.
* `writable`: True when CircuitPython and the web workflow can write to the disk. USB may claim a disk instead. * `writable`: True when CircuitPython and the web workflow can write to the disk. USB may claim a disk instead.
* `total`: Total bytes that make up the disk.
Example: Example:
```sh ```sh
@ -405,7 +418,7 @@ This is an authenticated endpoint in both modes.
Returns information about the device. Returns information about the device.
* `web_api_version`: Between `1` and `3`. This versions the rest of the API and new versions may not be backwards compatible. See below for more info. * `web_api_version`: Between `1` and `4`. This versions the rest of the API and new versions may not be backwards compatible. See below for more info.
* `version`: CircuitPython build version. * `version`: CircuitPython build version.
* `build_date`: CircuitPython build date. * `build_date`: CircuitPython build date.
* `board_name`: Human readable name of the board. * `board_name`: Human readable name of the board.
@ -467,3 +480,5 @@ Only one WebSocket at a time is supported.
* `1` - Initial version. * `1` - Initial version.
* `2` - Added `/cp/diskinfo.json`. * `2` - Added `/cp/diskinfo.json`.
* `3` - Changed `/cp/diskinfo.json` to return a list in preparation for multi-disk support. * `3` - Changed `/cp/diskinfo.json` to return a list in preparation for multi-disk support.
* `4` - Changed directory json to an object with additional data. File list is under `files` and is
the same as the old format.

View file

@ -48,6 +48,8 @@
#define MP_BLOCKDEV_FLAG_USB_WRITABLE (0x0010) #define MP_BLOCKDEV_FLAG_USB_WRITABLE (0x0010)
// Bit set when the above flag is checked before opening a file for write. // Bit set when the above flag is checked before opening a file for write.
#define MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED (0x0020) #define MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED (0x0020)
// Bit set when something has claimed the right to mutate the blockdev.
#define MP_BLOCKDEV_FLAG_LOCKED (0x0040)
// constants for block protocol ioctl // constants for block protocol ioctl
#define MP_BLOCKDEV_IOCTL_INIT (1) #define MP_BLOCKDEV_IOCTL_INIT (1)

View file

@ -30,12 +30,41 @@
#include "py/mperrno.h" #include "py/mperrno.h"
#include "extmod/vfs.h" #include "extmod/vfs.h"
#if CIRCUITPY_SDCARDIO
#include "shared-bindings/sdcardio/SDCard.h"
#endif
#if CIRCUITPY_SDIOIO
#include "shared-bindings/sdioio/SDCard.h"
#endif
#if MICROPY_VFS #if MICROPY_VFS
void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) { void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) {
mp_load_method(bdev, MP_QSTR_readblocks, self->readblocks); mp_load_method(bdev, MP_QSTR_readblocks, self->readblocks);
mp_load_method_maybe(bdev, MP_QSTR_writeblocks, self->writeblocks); mp_load_method_maybe(bdev, MP_QSTR_writeblocks, self->writeblocks);
mp_load_method_maybe(bdev, MP_QSTR_ioctl, self->u.ioctl); mp_load_method_maybe(bdev, MP_QSTR_ioctl, self->u.ioctl);
// CIRCUITPY-CHANGE: Support native SD cards.
#if CIRCUITPY_SDCARDIO
if (mp_obj_get_type(bdev) == &sdcardio_SDCard_type) {
self->flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL;
self->readblocks[0] = mp_const_none;
self->readblocks[1] = bdev;
self->readblocks[2] = (mp_obj_t)sdcardio_sdcard_readblocks; // native version
self->writeblocks[0] = mp_const_none;
self->writeblocks[1] = bdev;
self->writeblocks[2] = (mp_obj_t)sdcardio_sdcard_writeblocks; // native version
self->u.ioctl[0] = mp_const_none;
self->u.ioctl[1] = bdev;
self->u.ioctl[2] = (mp_obj_t)sdcardio_sdcard_ioctl; // native version
}
#endif
#if CIRCUITPY_SDIOIO
if (mp_obj_get_type(bdev) == &sdioio_SDCard_type) {
// TODO: Enable native blockdev for SDIO too.
}
#endif
if (self->u.ioctl[0] != MP_OBJ_NULL) { if (self->u.ioctl[0] != MP_OBJ_NULL) {
// Device supports new block protocol, so indicate it // Device supports new block protocol, so indicate it
self->flags |= MP_BLOCKDEV_FLAG_HAVE_IOCTL; self->flags |= MP_BLOCKDEV_FLAG_HAVE_IOCTL;
@ -48,8 +77,10 @@ void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) {
int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf) { int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf) {
if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) { if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) {
mp_uint_t (*f)(uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->readblocks[2]; // CIRCUITPY-CHANGE: Pass the blockdev object into native readblocks so
return f(buf, block_num, num_blocks); // it has the corresponding state.
mp_uint_t (*f)(mp_obj_t self, uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->readblocks[2];
return f(self->readblocks[1], buf, block_num, num_blocks);
} else { } else {
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks *self->block_size, buf}; mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks *self->block_size, buf};
self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num); self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
@ -80,8 +111,10 @@ int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_
} }
if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) { if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) {
mp_uint_t (*f)(const uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->writeblocks[2]; // CIRCUITPY-CHANGE: Pass the blockdev object into native readblocks so
return f(buf, block_num, num_blocks); // it has the corresponding state.
mp_uint_t (*f)(mp_obj_t self, const uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->writeblocks[2];
return f(self->writeblocks[1], buf, block_num, num_blocks);
} else { } else {
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks *self->block_size, (void *)buf}; mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks *self->block_size, (void *)buf};
self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num); self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
@ -112,6 +145,16 @@ int mp_vfs_blockdev_write_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t
mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg) { mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg) {
if (self->flags & MP_BLOCKDEV_FLAG_HAVE_IOCTL) { if (self->flags & MP_BLOCKDEV_FLAG_HAVE_IOCTL) {
// CIRCUITPY-CHANGE: Support native IOCTL so it can run outside of the VM.
if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) {
size_t out_value;
bool (*f)(mp_obj_t self, uint32_t, uint32_t, size_t *) = (void *)(uintptr_t)self->u.ioctl[2];
bool b = f(self->u.ioctl[1], cmd, arg, &out_value);
if (!b) {
return mp_const_none;
}
return MP_OBJ_NEW_SMALL_INT(out_value);
}
// New protocol with ioctl // New protocol with ioctl
self->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(cmd); self->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(cmd);
self->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(arg); self->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(arg);

View file

@ -34,6 +34,10 @@ typedef struct _fs_user_mount_t {
mp_obj_base_t base; mp_obj_base_t base;
mp_vfs_blockdev_t blockdev; mp_vfs_blockdev_t blockdev;
FATFS fatfs; FATFS fatfs;
// CIRCUITPY-CHANGE: Count the users that are manipulating the blockdev via
// native fatfs so we can lock and unlock the blockdev.
int8_t lock_count;
} fs_user_mount_t; } fs_user_mount_t;
extern const byte fresult_to_errno_table[20]; extern const byte fresult_to_errno_table[20];

@ -1 +1 @@
Subproject commit 267219f161d002e7a724859e01d000a88dc08683 Subproject commit 76dd808fa4a8bc5c20fa2660d3b45ce9b33e2be6

@ -1 +1 @@
Subproject commit f975229b3f0182e7ea857446ca610dee6e54cc95 Subproject commit f90a7cbccfd698f6c2fb36bf787295bcf9ddb910

@ -1 +1 @@
Subproject commit 1f35b4a552045bd1a216507b17833960364dce2c Subproject commit 0adb75b898a133d929eb14baa2e54b7e9e23899c

@ -1 +1 @@
Subproject commit 4754bf3e5fdb559be9ea085bfb65bd435039e887 Subproject commit 178dbc30ff660fb93dc8fd8d1c193a00067398e4

@ -1 +1 @@
Subproject commit 8efd9f76ceaeae0fc43892108ff71335b8da1888 Subproject commit 5417f6225fb0573853972852ebdfa3aa080fed93

@ -1 +1 @@
Subproject commit 3203fbaea4f6ebc97ff7c3a1dc8dfaa899ff6216 Subproject commit b9c8eedd7b2c7e657ebb8195dde7a6190ae9b866

@ -1 +1 @@
Subproject commit db3b03c4c68a4d4d32a3d145f6fad8935a89a345 Subproject commit 7469b5fd5e24b856f01d59a03eed1c8e7049f0d9

View file

@ -207,7 +207,8 @@ msgid "%q must be multiple of 8."
msgstr "" msgstr ""
#: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c
#: shared-bindings/canio/CAN.c shared-bindings/digitalio/Pull.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c
#: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c
#: shared-module/synthio/Synthesizer.c #: shared-module/synthio/Synthesizer.c
msgid "%q must be of type %q or %q, not %q" msgid "%q must be of type %q or %q, not %q"
msgstr "" msgstr ""
@ -216,7 +217,7 @@ msgstr ""
msgid "%q must be of type %q, %q, or %q, not %q" msgid "%q must be of type %q, %q, or %q, not %q"
msgstr "" msgstr ""
#: py/argcheck.c shared-bindings/bitmapfilter/__init__.c #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c
#: shared-module/synthio/__init__.c #: shared-module/synthio/__init__.c
msgid "%q must be of type %q, not %q" msgid "%q must be of type %q, not %q"
msgstr "" msgstr ""
@ -234,7 +235,7 @@ msgstr ""
#: ports/nrf/common-hal/pulseio/PulseIn.c #: ports/nrf/common-hal/pulseio/PulseIn.c
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#: ports/stm/common-hal/pulseio/PulseIn.c py/argcheck.c #: ports/stm/common-hal/pulseio/PulseIn.c py/argcheck.c
#: shared-bindings/canio/Match.c #: shared-bindings/canio/Match.c shared-bindings/time/__init__.c
msgid "%q out of range" msgid "%q out of range"
msgstr "" msgstr ""
@ -498,7 +499,6 @@ msgstr ""
#: ports/nrf/common-hal/countio/Counter.c #: ports/nrf/common-hal/countio/Counter.c
#: ports/nrf/common-hal/pulseio/PulseIn.c #: ports/nrf/common-hal/pulseio/PulseIn.c
#: ports/nrf/common-hal/rotaryio/IncrementalEncoder.c #: ports/nrf/common-hal/rotaryio/IncrementalEncoder.c
#: shared-bindings/pwmio/PWMOut.c
msgid "All channels in use" msgid "All channels in use"
msgstr "" msgstr ""
@ -521,13 +521,11 @@ msgid "All sync event channels in use"
msgstr "" msgstr ""
#: ports/raspberrypi/common-hal/picodvi/Framebuffer.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer.c
#: shared-bindings/pwmio/PWMOut.c
msgid "All timers for this pin are in use" msgid "All timers for this pin are in use"
msgstr "" msgstr ""
#: ports/atmel-samd/common-hal/_pew/PewPew.c #: ports/atmel-samd/common-hal/_pew/PewPew.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c #: ports/atmel-samd/common-hal/pulseio/PulseOut.c
#: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/cxd56/common-hal/pulseio/PulseOut.c
@ -538,7 +536,7 @@ msgstr ""
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c #: ports/stm/peripherals/timers.c
msgid "All timers in use" msgid "All timers in use"
msgstr "" msgstr ""
@ -778,12 +776,6 @@ msgstr ""
msgid "Cannot remount '/' when visible via USB." msgid "Cannot remount '/' when visible via USB."
msgstr "" msgstr ""
#: ports/atmel-samd/common-hal/microcontroller/__init__.c
#: ports/cxd56/common-hal/microcontroller/__init__.c
#: ports/mimxrt10xx/common-hal/microcontroller/__init__.c
msgid "Cannot reset into bootloader because no bootloader is present"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c #: ports/espressif/common-hal/socketpool/Socket.c
msgid "Cannot set socket options" msgid "Cannot set socket options"
msgstr "" msgstr ""
@ -801,10 +793,6 @@ msgstr ""
msgid "Cannot subclass slice" msgid "Cannot subclass slice"
msgstr "" msgstr ""
#: shared-bindings/pwmio/PWMOut.c
msgid "Cannot vary frequency on a timer that is already in use"
msgstr ""
#: ports/nrf/common-hal/alarm/pin/PinAlarm.c #: ports/nrf/common-hal/alarm/pin/PinAlarm.c
msgid "Cannot wake on pin edge, only level" msgid "Cannot wake on pin edge, only level"
msgstr "" msgstr ""
@ -847,10 +835,6 @@ msgstr ""
msgid "Could not set address" msgid "Could not set address"
msgstr "" msgstr ""
#: shared-bindings/pwmio/PWMOut.c
msgid "Could not start PWM"
msgstr ""
#: ports/stm/common-hal/busio/UART.c #: ports/stm/common-hal/busio/UART.c
msgid "Could not start interrupt, RX busy" msgid "Could not start interrupt, RX busy"
msgstr "" msgstr ""
@ -942,16 +926,6 @@ msgstr ""
msgid "ESP-IDF memory allocation failed" msgid "ESP-IDF memory allocation failed"
msgstr "" msgstr ""
#: ports/atmel-samd/common-hal/alarm/pin/PinAlarm.c
#: ports/atmel-samd/common-hal/countio/Counter.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
#: ports/cxd56/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr ""
#: extmod/modre.c #: extmod/modre.c
msgid "Error in regex" msgid "Error in regex"
msgstr "" msgstr ""
@ -1084,10 +1058,6 @@ msgid ""
"Frequency must be 24, 150, 396, 450, 528, 600, 720, 816, 912, 960 or 1008 Mhz" "Frequency must be 24, 150, 396, 450, 528, 600, 720, 816, 912, 960 or 1008 Mhz"
msgstr "" msgstr ""
#: shared-bindings/pwmio/PWMOut.c
msgid "Frequency must match existing PWMOut using this timer"
msgstr ""
#: shared-bindings/bitbangio/I2C.c shared-bindings/bitbangio/SPI.c #: shared-bindings/bitbangio/I2C.c shared-bindings/bitbangio/SPI.c
#: shared-bindings/busio/I2C.c shared-bindings/busio/SPI.c #: shared-bindings/busio/I2C.c shared-bindings/busio/SPI.c
msgid "Function requires lock" msgid "Function requires lock"
@ -1122,11 +1092,6 @@ msgstr ""
msgid "Heap allocation when VM not running." msgid "Heap allocation when VM not running."
msgstr "" msgstr ""
#: supervisor/shared/safe_mode.c
msgid ""
"Heap was corrupted because the stack was too small. Increase stack size."
msgstr ""
#: extmod/vfs_posix_file.c py/objstringio.c #: extmod/vfs_posix_file.c py/objstringio.c
msgid "I/O operation on closed file" msgid "I/O operation on closed file"
msgstr "" msgstr ""
@ -1202,7 +1167,7 @@ msgid "Internal define error"
msgstr "" msgstr ""
#: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c
#: shared-module/os/getenv.c #: shared-bindings/pwmio/PWMOut.c shared-module/os/getenv.c
msgid "Internal error" msgid "Internal error"
msgstr "" msgstr ""
@ -1211,6 +1176,16 @@ msgstr ""
msgid "Internal error #%d" msgid "Internal error #%d"
msgstr "" msgstr ""
#: ports/atmel-samd/common-hal/alarm/pin/PinAlarm.c
#: ports/atmel-samd/common-hal/countio/Counter.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
#: ports/cxd56/common-hal/pulseio/PulseIn.c shared-bindings/pwmio/PWMOut.c
msgid "Internal resource(s) in use"
msgstr ""
#: supervisor/shared/safe_mode.c #: supervisor/shared/safe_mode.c
msgid "Internal watchdog timer expired." msgid "Internal watchdog timer expired."
msgstr "" msgstr ""
@ -1228,7 +1203,7 @@ msgstr ""
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c
#: ports/raspberrypi/common-hal/picodvi/Framebuffer.c py/argcheck.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer.c py/argcheck.c
#: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/digitalio/DigitalInOut.c
#: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c
msgid "Invalid %q" msgid "Invalid %q"
msgstr "" msgstr ""
@ -1376,6 +1351,10 @@ msgstr ""
msgid "Missing jmp_pin. %q[%u] jumps on pin" msgid "Missing jmp_pin. %q[%u] jumps on pin"
msgstr "" msgstr ""
#: shared-module/storage/__init__.c
msgid "Mount point directory missing"
msgstr ""
#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c #: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c
msgid "Must be a %q subclass." msgid "Must be a %q subclass."
msgstr "" msgstr ""
@ -1460,8 +1439,10 @@ msgstr ""
msgid "No IP" msgid "No IP"
msgstr "" msgstr ""
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/microcontroller/__init__.c
msgid "No available clocks" #: ports/cxd56/common-hal/microcontroller/__init__.c
#: ports/mimxrt10xx/common-hal/microcontroller/__init__.c
msgid "No bootloader present"
msgstr "" msgstr ""
#: ports/espressif/common-hal/imagecapture/ParallelImageCapture.c #: ports/espressif/common-hal/imagecapture/ParallelImageCapture.c
@ -1480,15 +1461,12 @@ msgstr ""
msgid "No default %q bus" msgid "No default %q bus"
msgstr "" msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
#: ports/atmel-samd/common-hal/touchio/TouchIn.c #: ports/atmel-samd/common-hal/touchio/TouchIn.c
msgid "No free GCLKs" msgid "No free GCLKs"
msgstr "" msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "No free GLCKs"
msgstr ""
#: shared-bindings/os/__init__.c #: shared-bindings/os/__init__.c
msgid "No hardware random available" msgid "No hardware random available"
msgstr "" msgstr ""
@ -1687,11 +1665,6 @@ msgstr ""
msgid "Out-buffer elements must be <= 4 bytes long" msgid "Out-buffer elements must be <= 4 bytes long"
msgstr "" msgstr ""
#: shared-bindings/pwmio/PWMOut.c
msgid ""
"PWM frequency not writable when variable_frequency is False on construction."
msgstr ""
#: ports/stm/common-hal/pwmio/PWMOut.c #: ports/stm/common-hal/pwmio/PWMOut.c
msgid "PWM restart" msgid "PWM restart"
msgstr "" msgstr ""
@ -1737,11 +1710,6 @@ msgstr ""
msgid "Pin must be on PWM Channel B" msgid "Pin must be on PWM Channel B"
msgstr "" msgstr ""
#: ports/atmel-samd/common-hal/countio/Counter.c
#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
msgid "Pin must support hardware interrupts"
msgstr ""
#: shared-bindings/rgbmatrix/RGBMatrix.c #: shared-bindings/rgbmatrix/RGBMatrix.c
#, c-format #, c-format
msgid "" msgid ""
@ -1972,6 +1940,10 @@ msgstr ""
msgid "Specify exactly one of data0 or data_pins" msgid "Specify exactly one of data0 or data_pins"
msgstr "" msgstr ""
#: supervisor/shared/safe_mode.c
msgid "Stack overflow. Increase stack size."
msgstr ""
#: shared-bindings/alarm/time/TimeAlarm.c #: shared-bindings/alarm/time/TimeAlarm.c
msgid "Supply one of monotonic_time or epoch_time" msgid "Supply one of monotonic_time or epoch_time"
msgstr "" msgstr ""
@ -2078,10 +2050,6 @@ msgstr ""
msgid "Traceback (most recent call last):\n" msgid "Traceback (most recent call last):\n"
msgstr "" msgstr ""
#: shared-bindings/time/__init__.c
msgid "Tuple or struct_time argument required"
msgstr ""
#: ports/stm/common-hal/busio/UART.c #: ports/stm/common-hal/busio/UART.c
msgid "UART de-init" msgid "UART de-init"
msgstr "" msgstr ""
@ -2435,10 +2403,6 @@ msgstr ""
msgid "argsort is not implemented for flattened arrays" msgid "argsort is not implemented for flattened arrays"
msgstr "" msgstr ""
#: py/runtime.c shared-bindings/supervisor/__init__.c
msgid "argument has wrong type"
msgstr ""
#: py/compile.c #: py/compile.c
msgid "argument name reused" msgid "argument name reused"
msgstr "" msgstr ""
@ -2448,10 +2412,6 @@ msgstr ""
msgid "argument num/types mismatch" msgid "argument num/types mismatch"
msgstr "" msgstr ""
#: py/runtime.c
msgid "argument should be a '%q' not a '%q'"
msgstr ""
#: extmod/ulab/code/numpy/numerical.c extmod/ulab/code/numpy/transform.c #: extmod/ulab/code/numpy/numerical.c extmod/ulab/code/numpy/transform.c
msgid "arguments must be ndarrays" msgid "arguments must be ndarrays"
msgstr "" msgstr ""
@ -2636,7 +2596,7 @@ msgstr ""
msgid "can't convert %s to float" msgid "can't convert %s to float"
msgstr "" msgstr ""
#: py/runtime.c #: py/objint.c py/runtime.c
#, c-format #, c-format
msgid "can't convert %s to int" msgid "can't convert %s to int"
msgstr "" msgstr ""
@ -2645,18 +2605,10 @@ msgstr ""
msgid "can't convert '%q' object to %q implicitly" msgid "can't convert '%q' object to %q implicitly"
msgstr "" msgstr ""
#: py/objint.c
msgid "can't convert NaN to int"
msgstr ""
#: extmod/ulab/code/numpy/vector.c #: extmod/ulab/code/numpy/vector.c
msgid "can't convert complex to float" msgid "can't convert complex to float"
msgstr "" msgstr ""
#: py/objint.c
msgid "can't convert inf to int"
msgstr ""
#: py/obj.c #: py/obj.c
msgid "can't convert to complex" msgid "can't convert to complex"
msgstr "" msgstr ""
@ -3144,10 +3096,6 @@ msgstr ""
msgid "function takes %d positional arguments but %d were given" msgid "function takes %d positional arguments but %d were given"
msgstr "" msgstr ""
#: shared-bindings/time/__init__.c
msgid "function takes exactly 9 arguments"
msgstr ""
#: py/objgenerator.c #: py/objgenerator.c
msgid "generator already executing" msgid "generator already executing"
msgstr "" msgstr ""
@ -3998,10 +3946,6 @@ msgstr ""
msgid "size is defined for ndarrays only" msgid "size is defined for ndarrays only"
msgstr "" msgstr ""
#: shared-bindings/time/__init__.c
msgid "sleep length must be non-negative"
msgstr ""
#: py/nativeglue.c #: py/nativeglue.c
msgid "slice unsupported" msgid "slice unsupported"
msgstr "" msgstr ""

2
main.c
View file

@ -1099,7 +1099,7 @@ int __attribute__((used)) main(void) {
exit_code = run_repl(get_safe_mode()); exit_code = run_repl(get_safe_mode());
supervisor_set_run_reason(RUN_REASON_REPL_RELOAD); supervisor_set_run_reason(RUN_REASON_REPL_RELOAD);
} }
if (exit_code == PYEXEC_FORCED_EXIT) { if (exit_code & (PYEXEC_FORCED_EXIT | PYEXEC_RELOAD)) {
if (!simulate_reset) { if (!simulate_reset) {
serial_write_compressed(MP_ERROR_TEXT("soft reboot\n")); serial_write_compressed(MP_ERROR_TEXT("soft reboot\n"));
} }

View file

@ -235,7 +235,7 @@ static void pinalarm_set_alarms_light(size_t n_alarms, const mp_obj_t *alarms) {
case PINALARM_ERR_NOEXTINT: case PINALARM_ERR_NOEXTINT:
raise_ValueError_invalid_pin(); raise_ValueError_invalid_pin();
case PINALARM_ERR_NOCHANNEL: case PINALARM_ERR_NOCHANNEL:
mp_raise_RuntimeError(MP_ERROR_TEXT("EXTINT channel already in use")); mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
default: default:
mp_raise_RuntimeError(MP_ERROR_TEXT("Unknown reason.")); mp_raise_RuntimeError(MP_ERROR_TEXT("Unknown reason."));
} }

View file

@ -243,7 +243,7 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self,
// Find a free GCLK to generate the MCLK signal. // Find a free GCLK to generate the MCLK signal.
uint8_t gclk = find_free_gclk(divisor); uint8_t gclk = find_free_gclk(divisor);
if (gclk > GCLK_GEN_NUM) { if (gclk > GCLK_GEN_NUM) {
mp_raise_RuntimeError(MP_ERROR_TEXT("No free GLCKs")); mp_raise_RuntimeError(MP_ERROR_TEXT("No free GCLKs"));
} }
self->gclk = gclk; self->gclk = gclk;

View file

@ -1,6 +1,7 @@
#include "common-hal/countio/Counter.h" #include "common-hal/countio/Counter.h"
#include "shared-bindings/countio/Counter.h" #include "shared-bindings/countio/Counter.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "atmel_start_pins.h" #include "atmel_start_pins.h"
@ -11,13 +12,13 @@
void common_hal_countio_counter_construct(countio_counter_obj_t *self, void common_hal_countio_counter_construct(countio_counter_obj_t *self,
const mcu_pin_obj_t *pin, countio_edge_t edge, digitalio_pull_t pull) { const mcu_pin_obj_t *pin, countio_edge_t edge, digitalio_pull_t pull) {
if (!pin->has_extint) { if (!pin->has_extint) {
mp_raise_RuntimeError(MP_ERROR_TEXT("Pin must support hardware interrupts")); raise_ValueError_invalid_pin();
} }
if (eic_get_enable()) { if (eic_get_enable()) {
if (!eic_channel_free(pin->extint_channel)) { if (!eic_channel_free(pin->extint_channel)) {
mp_raise_RuntimeError(MP_ERROR_TEXT("EXTINT channel already in use")); mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
} }
} else { } else {
turn_on_external_interrupt_controller(); turn_on_external_interrupt_controller();

View file

@ -295,12 +295,12 @@ void common_hal_frequencyio_frequencyin_construct(frequencyio_frequencyin_obj_t*
#ifdef SAM_D5X_E5X #ifdef SAM_D5X_E5X
((EIC->INTENSET.bit.EXTINT & mask) != 0 || (EIC->EVCTRL.bit.EXTINTEO & mask) != 0)) { ((EIC->INTENSET.bit.EXTINT & mask) != 0 || (EIC->EVCTRL.bit.EXTINTEO & mask) != 0)) {
#endif #endif
mp_raise_RuntimeError(MP_ERROR_TEXT("EXTINT channel already in use")); mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
} }
uint8_t timer_index = find_free_timer(); uint8_t timer_index = find_free_timer();
if (timer_index == 0xff) { if (timer_index == 0xff) {
mp_raise_RuntimeError(MP_ERROR_TEXT("All timers in use")); mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
} }
Tc *tc = tc_insts[timer_index]; Tc *tc = tc_insts[timer_index];
@ -329,7 +329,7 @@ void common_hal_frequencyio_frequencyin_construct(frequencyio_frequencyin_obj_t*
frequencyin_samd51_start_dpll(); frequencyin_samd51_start_dpll();
if (dpll_gclk == 0xff && !clock_get_enabled(0, GCLK_SOURCE_DPLL1)) { if (dpll_gclk == 0xff && !clock_get_enabled(0, GCLK_SOURCE_DPLL1)) {
common_hal_frequencyio_frequencyin_deinit(self); common_hal_frequencyio_frequencyin_deinit(self);
mp_raise_RuntimeError(MP_ERROR_TEXT("No available clocks")); mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
} }
set_timer_handler(timer_index, dpll_gclk, TC_HANDLER_NO_INTERRUPT); set_timer_handler(timer_index, dpll_gclk, TC_HANDLER_NO_INTERRUPT);
turn_on_clocks(true, timer_index, dpll_gclk); turn_on_clocks(true, timer_index, dpll_gclk);
@ -399,7 +399,7 @@ void common_hal_frequencyio_frequencyin_construct(frequencyio_frequencyin_obj_t*
reference_tc = find_free_timer(); reference_tc = find_free_timer();
if (reference_tc == 0xff) { if (reference_tc == 0xff) {
common_hal_frequencyio_frequencyin_deinit(self); common_hal_frequencyio_frequencyin_deinit(self);
mp_raise_RuntimeError(MP_ERROR_TEXT("All timers in use")); mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
} }
frequencyin_reference_tc_init(); frequencyin_reference_tc_init();
} }

View file

@ -64,7 +64,7 @@ void common_hal_mcu_enable_interrupts(void) {
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
if ((runmode == RUNMODE_BOOTLOADER) || (runmode == RUNMODE_UF2)) { if ((runmode == RUNMODE_BOOTLOADER) || (runmode == RUNMODE_UF2)) {
if (!bootloader_available()) { if (!bootloader_available()) {
mp_raise_ValueError(MP_ERROR_TEXT("Cannot reset into bootloader because no bootloader is present")); mp_raise_ValueError(MP_ERROR_TEXT("No bootloader present"));
} }
// Pretend to be the first of the two reset presses needed to enter the // Pretend to be the first of the two reset presses needed to enter the
// bootloader. That way one reset will end in the bootloader. // bootloader. That way one reset will end in the bootloader.

View file

@ -248,7 +248,7 @@ void common_hal_ps2io_ps2_construct(ps2io_ps2_obj_t *self,
mp_arg_error_invalid(MP_QSTR_clock_pin); mp_arg_error_invalid(MP_QSTR_clock_pin);
} }
if (eic_get_enable() && !eic_channel_free(clock_pin->extint_channel)) { if (eic_get_enable() && !eic_channel_free(clock_pin->extint_channel)) {
mp_raise_RuntimeError(MP_ERROR_TEXT("EXTINT channel already in use")); mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
} }
clk_hi(self); clk_hi(self);

View file

@ -155,7 +155,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self,
raise_ValueError_invalid_pin(); raise_ValueError_invalid_pin();
} }
if (eic_get_enable() && !eic_channel_free(pin->extint_channel)) { if (eic_get_enable() && !eic_channel_free(pin->extint_channel)) {
mp_raise_RuntimeError(MP_ERROR_TEXT("EXTINT channel already in use")); mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
} }
self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t)); self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t));

View file

@ -150,7 +150,6 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
// one output so we start with the TCs to see if they work. // one output so we start with the TCs to see if they work.
int8_t direction = -1; int8_t direction = -1;
uint8_t start = NUM_TIMERS_PER_PIN - 1; uint8_t start = NUM_TIMERS_PER_PIN - 1;
bool found = false;
if (variable_frequency) { if (variable_frequency) {
direction = 1; direction = 1;
start = 0; start = 0;
@ -162,7 +161,6 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
continue; continue;
} }
if (t->is_tc) { if (t->is_tc) {
found = true;
Tc *tc = tc_insts[t->index]; Tc *tc = tc_insts[t->index];
if (tc->COUNT16.CTRLA.bit.ENABLE == 0 && t->wave_output == 1) { if (tc->COUNT16.CTRLA.bit.ENABLE == 0 && t->wave_output == 1) {
timer = t; timer = t;
@ -178,10 +176,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
} }
if (timer == NULL) { if (timer == NULL) {
if (found) { return PWMOUT_INTERNAL_RESOURCES_IN_USE;
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
}
return PWMOUT_ALL_TIMERS_IN_USE;
} }
uint8_t resolution = 0; uint8_t resolution = 0;

View file

@ -25,6 +25,7 @@
*/ */
#include "common-hal/rotaryio/IncrementalEncoder.h" #include "common-hal/rotaryio/IncrementalEncoder.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/rotaryio/IncrementalEncoder.h" #include "shared-bindings/rotaryio/IncrementalEncoder.h"
#include "shared-module/rotaryio/IncrementalEncoder.h" #include "shared-module/rotaryio/IncrementalEncoder.h"
@ -36,8 +37,11 @@
void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self, void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self,
const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) { const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) {
if (!pin_a->has_extint || !pin_b->has_extint) { if (!pin_a->has_extint) {
mp_raise_RuntimeError(MP_ERROR_TEXT("Pin must support hardware interrupts")); raise_ValueError_invalid_pin_name(MP_QSTR_pin_a);
}
if (!pin_b->has_extint) {
raise_ValueError_invalid_pin_name(MP_QSTR_pin_b);
} }
// TODO: The SAMD51 has a peripheral dedicated to quadrature encoder debugging. Use it instead // TODO: The SAMD51 has a peripheral dedicated to quadrature encoder debugging. Use it instead
@ -45,7 +49,7 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode
if (eic_get_enable()) { if (eic_get_enable()) {
if (!eic_channel_free(pin_a->extint_channel) || !eic_channel_free(pin_b->extint_channel)) { if (!eic_channel_free(pin_a->extint_channel) || !eic_channel_free(pin_b->extint_channel)) {
mp_raise_RuntimeError(MP_ERROR_TEXT("EXTINT channel already in use")); mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
} }
} else { } else {
turn_on_external_interrupt_controller(); turn_on_external_interrupt_controller();

View file

@ -72,7 +72,7 @@ void common_hal_mcu_enable_interrupts(void) {
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
if (runmode == RUNMODE_BOOTLOADER) { if (runmode == RUNMODE_BOOTLOADER) {
mp_raise_ValueError(MP_ERROR_TEXT("Cannot reset into bootloader because no bootloader is present")); mp_raise_ValueError(MP_ERROR_TEXT("No bootloader present"));
} else if (runmode == RUNMODE_SAFE_MODE) { } else if (runmode == RUNMODE_SAFE_MODE) {
safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC); safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC);
} }

View file

@ -100,7 +100,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self,
int irq = pulsein_set_config(self, true); int irq = pulsein_set_config(self, true);
if (irq < 0) { if (irq < 0) {
mp_raise_RuntimeError(MP_ERROR_TEXT("EXTINT channel already in use")); mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
} else { } else {
pulsein_objects[irq - CXD56_IRQ_EXDEVICE_0] = self; pulsein_objects[irq - CXD56_IRQ_EXDEVICE_0] = self;
} }

View file

@ -0,0 +1,29 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
*
* 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 "supervisor/board.h"
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.

View file

@ -0,0 +1,43 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Dan Halbert for Adafruit Industries
*
* 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.
*/
// Micropython setup
#define MICROPY_HW_BOARD_NAME "Espressif ESP32 DevKitc V4 WROOM-32E"
#define MICROPY_HW_MCU_NAME "ESP32"
#define CIRCUITPY_BOARD_I2C (1)
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO22, .sda = &pin_GPIO23}}
#define CIRCUITPY_BOARD_SPI (1)
#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO5, .mosi = &pin_GPIO18, .miso = &pin_GPIO19}}
#define CIRCUITPY_BOARD_UART (1)
#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO17, .rx = &pin_GPIO16}}
// UART pins attached to the USB-serial converter chip
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3)

View file

@ -0,0 +1,10 @@
CIRCUITPY_CREATOR_ID = 0x000C303A
CIRCUITPY_CREATION_ID = 0x0032C002
IDF_TARGET = esp32
CIRCUITPY_ESP_FLASH_MODE = qio
CIRCUITPY_ESP_FLASH_FREQ = 40m
CIRCUITPY_ESP_FLASH_SIZE = 4MB
CIRCUITPY_ESPCAMERA = 0

View file

@ -0,0 +1,70 @@
#include "shared-bindings/board/__init__.h"
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
// External pins are in silkscreen order, from top to bottom, left side, then right side
// Left Side
// Pins dedicated to SPI flash
{ MP_ROM_QSTR(MP_QSTR_CLK), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) },
// Normal pins
{ MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) },
// UART on silkscreen
{ MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO1) },
// Normal pins
{ MP_ROM_QSTR(MP_QSTR_IO22), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_IO23), MP_ROM_PTR(&pin_GPIO23) },
// Right side
// Pins dedicated to SPI flash
{ MP_ROM_QSTR(MP_QSTR_CMD), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) },
// Normal pins
{ MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_IO27), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_IO25), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_IO32), MP_ROM_PTR(&pin_GPIO32) },
// Input-only pins, VP/VN on silkscreen
{ MP_ROM_QSTR(MP_QSTR_I35), MP_ROM_PTR(&pin_GPIO35) },
{ MP_ROM_QSTR(MP_QSTR_I34), MP_ROM_PTR(&pin_GPIO34) },
{ MP_ROM_QSTR(MP_QSTR_I39), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_VN), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_I36), MP_ROM_PTR(&pin_GPIO36) },
{ MP_ROM_QSTR(MP_QSTR_VP), MP_ROM_PTR(&pin_GPIO36) },
// Button
{ MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View file

@ -0,0 +1,29 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
*
* 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 "supervisor/board.h"
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.

View file

@ -0,0 +1,43 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Dan Halbert for Adafruit Industries
*
* 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.
*/
// Micropython setup
#define MICROPY_HW_BOARD_NAME "Espressif ESP32 DevKitc V4 WROVER"
#define MICROPY_HW_MCU_NAME "ESP32"
#define CIRCUITPY_BOARD_I2C (1)
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO22, .sda = &pin_GPIO23}}
#define CIRCUITPY_BOARD_SPI (1)
#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO5, .mosi = &pin_GPIO18, .miso = &pin_GPIO19}}
#define CIRCUITPY_BOARD_UART (1)
#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO17, .rx = &pin_GPIO16}}
// UART pins attached to the USB-serial converter chip
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3)

View file

@ -0,0 +1,14 @@
CIRCUITPY_CREATOR_ID = 0x000C303A
CIRCUITPY_CREATION_ID = 0x0032C003
IDF_TARGET = esp32
CIRCUITPY_ESP_FLASH_MODE = qio
CIRCUITPY_ESP_FLASH_FREQ = 40m
CIRCUITPY_ESP_FLASH_SIZE = 8MB
CIRCUITPY_ESPCAMERA = 0
CIRCUITPY_ESP_PSRAM_SIZE = 8MB
CIRCUITPY_ESP_PSRAM_MODE = qio
CIRCUITPY_ESP_PSRAM_FREQ = 40m

View file

@ -0,0 +1,70 @@
#include "shared-bindings/board/__init__.h"
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
// External pins are in silkscreen order, from top to bottom, left side, then right side
// Left Side
// Pins dedicated to SPI flash & mem
{ MP_ROM_QSTR(MP_QSTR_CLK), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) },
// Normal pins
{ MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) },
// UART on silkscreen
{ MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO1) },
// Normal pins
{ MP_ROM_QSTR(MP_QSTR_IO22), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_IO23), MP_ROM_PTR(&pin_GPIO23) },
// Right side
// Pins dedicated to SPI flash & mem
{ MP_ROM_QSTR(MP_QSTR_CMD), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) },
// Normal pins
{ MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_IO27), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_IO25), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_IO32), MP_ROM_PTR(&pin_GPIO32) },
// Input-only pins, VP/VN on silkscreen
{ MP_ROM_QSTR(MP_QSTR_I35), MP_ROM_PTR(&pin_GPIO35) },
{ MP_ROM_QSTR(MP_QSTR_I34), MP_ROM_PTR(&pin_GPIO34) },
{ MP_ROM_QSTR(MP_QSTR_I39), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_VN), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_I36), MP_ROM_PTR(&pin_GPIO36) },
{ MP_ROM_QSTR(MP_QSTR_VP), MP_ROM_PTR(&pin_GPIO36) },
// Button
{ MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View file

@ -27,9 +27,8 @@
#define MICROPY_HW_BOARD_NAME "DFRobot FireBeetle 2 ESP32-S3" #define MICROPY_HW_BOARD_NAME "DFRobot FireBeetle 2 ESP32-S3"
#define MICROPY_HW_MCU_NAME "ESP32S3" #define MICROPY_HW_MCU_NAME "ESP32S3"
#define CIRCUITPY_BOARD_I2C (2) #define CIRCUITPY_BOARD_I2C (1)
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO2, .sda = &pin_GPIO3}, \ #define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO2, .sda = &pin_GPIO1}}
{.scl = &pin_GPIO2, .sda = &pin_GPIO1}}
#define DEFAULT_SPI_BUS_SCK (&pin_GPIO17) #define DEFAULT_SPI_BUS_SCK (&pin_GPIO17)
#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO15) #define DEFAULT_SPI_BUS_MOSI (&pin_GPIO15)

View file

@ -2,8 +2,6 @@
#include "shared-bindings/board/__init__.h" #include "shared-bindings/board/__init__.h"
#include "shared-module/displayio/__init__.h" #include "shared-module/displayio/__init__.h"
CIRCUITPY_BOARD_BUS_SINGLETON(cam_i2c, i2c, 1) // Camera sensor
STATIC const mp_rom_obj_tuple_t camera_data_tuple = { STATIC const mp_rom_obj_tuple_t camera_data_tuple = {
// The order matters. // The order matters.
// They must be ordered from low to high (Y2, Y3 .. Y9). // They must be ordered from low to high (Y2, Y3 .. Y9).
@ -43,9 +41,8 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO2) }, { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO3) }, { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO1) },
// I2C cannot be used when CAM_I2C is in use.
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) },
@ -118,7 +115,5 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_CAM_HREF), MP_ROM_PTR(&pin_GPIO42)}, { MP_ROM_QSTR(MP_QSTR_CAM_HREF), MP_ROM_PTR(&pin_GPIO42)},
{ MP_ROM_QSTR(MP_QSTR_CAM_PCLK), MP_ROM_PTR(&pin_GPIO5) }, { MP_ROM_QSTR(MP_QSTR_CAM_PCLK), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_CAM_XCLK), MP_ROM_PTR(&pin_GPIO45)}, { MP_ROM_QSTR(MP_QSTR_CAM_XCLK), MP_ROM_PTR(&pin_GPIO45)},
{ MP_ROM_QSTR(MP_QSTR_CAM_I2C), MP_ROM_PTR(&board_cam_i2c_obj)},
}; };
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View file

@ -73,6 +73,7 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
{ MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)} // TODO: Uncomment once the display initialization code is added.
// { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}
}; };
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View file

@ -36,7 +36,8 @@
void board_init(void) { void board_init(void) {
mp_import_stat_t stat_b = mp_import_stat("boot.py"); mp_import_stat_t stat_b = mp_import_stat("boot.py");
if (stat_b != MP_IMPORT_STAT_FILE) { if (stat_b != MP_IMPORT_STAT_FILE) {
FATFS *fatfs = filesystem_circuitpy(); fs_user_mount_t *fs_mount = filesystem_circuitpy();
FATFS *fatfs = &fs_mount->fatfs;
FIL fs; FIL fs;
UINT char_written = 0; UINT char_written = 0;
const byte buffer[] = "#Serial port upload mode\nimport storage\nstorage.remount(\"/\", False)\nstorage.disable_usb_drive()\n"; const byte buffer[] = "#Serial port upload mode\nimport storage\nstorage.remount(\"/\", False)\nstorage.disable_usb_drive()\n";
@ -44,7 +45,7 @@ void board_init(void) {
f_open(fatfs, &fs, "/boot.py", FA_WRITE | FA_CREATE_ALWAYS); f_open(fatfs, &fs, "/boot.py", FA_WRITE | FA_CREATE_ALWAYS);
f_write(&fs, buffer, sizeof(buffer) - 1, &char_written); f_write(&fs, buffer, sizeof(buffer) - 1, &char_written);
f_close(&fs); f_close(&fs);
// Delete code.Py, use main.py // Delete code.py, use main.py
mp_import_stat_t stat_c = mp_import_stat("code.py"); mp_import_stat_t stat_c = mp_import_stat("code.py");
if (stat_c == MP_IMPORT_STAT_FILE) { if (stat_c == MP_IMPORT_STAT_FILE) {
f_unlink(fatfs, "/code.py"); f_unlink(fatfs, "/code.py");

View file

@ -37,16 +37,16 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_I2S_MIC_SEL), MP_ROM_PTR(&pin_GPIO39) }, { MP_ROM_QSTR(MP_QSTR_I2S_MIC_SEL), MP_ROM_PTR(&pin_GPIO39) },
// I2S Amplifier MAX98357A // I2S Amplifier MAX98357A
{ MP_ROM_QSTR(MP_QSTR_I2S_MIC_LRCLK), MP_ROM_PTR(&pin_GPIO1) }, { MP_ROM_QSTR(MP_QSTR_I2S_AMP_LRCLK), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_I2S_MIC_BCLK), MP_ROM_PTR(&pin_GPIO2) }, { MP_ROM_QSTR(MP_QSTR_I2S_AMP_BCLK), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_I2S_MIC_DATA), MP_ROM_PTR(&pin_GPIO3) }, { MP_ROM_QSTR(MP_QSTR_I2S_AMP_DATA), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_I2S_MIC_SD), MP_ROM_PTR(&pin_GPIO4) }, { MP_ROM_QSTR(MP_QSTR_I2S_AMP_SD), MP_ROM_PTR(&pin_GPIO4) },
// RTC Interrupt Pin // RTC Interrupt Pin
{ MP_ROM_QSTR(MP_QSTR_RTC_INT), MP_ROM_PTR(&pin_GPIO7) }, { MP_ROM_QSTR(MP_QSTR_RTC_INT), MP_ROM_PTR(&pin_GPIO7) },
// LED Matrix // LED Matrix
{ MP_ROM_QSTR(MP_QSTR_MATRIX_POWER), MP_ROM_PTR(&pin_GPIO5) }, { MP_ROM_QSTR(MP_QSTR_MATRIX_POWER), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_MATRIX_DATA), MP_ROM_PTR(&pin_GPIO18) }, { MP_ROM_QSTR(MP_QSTR_MATRIX_DATA), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },

View file

@ -103,7 +103,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
} }
if (timer_index == INDEX_EMPTY) { if (timer_index == INDEX_EMPTY) {
// Running out of timers isn't pin related on ESP32S2. // Running out of timers isn't pin related on ESP32S2.
return PWMOUT_ALL_TIMERS_IN_USE; return PWMOUT_INTERNAL_RESOURCES_IN_USE;
} }
// Find a viable channel // Find a viable channel
@ -114,7 +114,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
} }
} }
if (channel_index == INDEX_EMPTY) { if (channel_index == INDEX_EMPTY) {
return PWMOUT_ALL_CHANNELS_IN_USE; return PWMOUT_INTERNAL_RESOURCES_IN_USE;
} }
// Run configuration // Run configuration

View file

@ -60,7 +60,8 @@ STATIC uint32_t _cache_lba = 0xffffffff;
#define SECSIZE(fs) ((fs)->ssize) #define SECSIZE(fs) ((fs)->ssize)
#endif // FF_MAX_SS == FF_MIN_SS #endif // FF_MAX_SS == FF_MIN_SS
STATIC DWORD fatfs_bytes(void) { STATIC DWORD fatfs_bytes(void) {
FATFS *fatfs = filesystem_circuitpy(); fs_user_mount_t *fs_mount = filesystem_circuitpy();
FATFS *fatfs = &fs_mount->fatfs;
return (fatfs->csize * SECSIZE(fatfs)) * (fatfs->n_fatent - 2); return (fatfs->csize * SECSIZE(fatfs)) * (fatfs->n_fatent - 2);
} }
STATIC bool storage_extended = true; STATIC bool storage_extended = true;

View file

@ -107,9 +107,6 @@
#include "esp_log.h" #include "esp_log.h"
#define TAG "port" #define TAG "port"
uint32_t *heap;
uint32_t heap_size;
STATIC esp_timer_handle_t _tick_timer; STATIC esp_timer_handle_t _tick_timer;
STATIC esp_timer_handle_t _sleep_timer; STATIC esp_timer_handle_t _sleep_timer;
@ -255,9 +252,6 @@ safe_mode_t port_init(void) {
esp_rom_install_uart_printf(); esp_rom_install_uart_printf();
#endif #endif
heap = NULL;
heap_size = 0;
#define pin_GPIOn(n) pin_GPIO##n #define pin_GPIOn(n) pin_GPIO##n
#define pin_GPIOn_EXPAND(x) pin_GPIOn(x) #define pin_GPIOn_EXPAND(x) pin_GPIOn(x)
@ -329,7 +323,16 @@ void *port_malloc(size_t size, bool dma_capable) {
if (dma_capable) { if (dma_capable) {
caps |= MALLOC_CAP_DMA; caps |= MALLOC_CAP_DMA;
} }
return heap_caps_malloc(size, caps);
void *ptr = NULL;
// Try SPIRAM first when available.
#ifdef CONFIG_SPIRAM
ptr = heap_caps_malloc(size, caps | MALLOC_CAP_SPIRAM);
#endif
if (ptr == NULL) {
ptr = heap_caps_malloc(size, caps);
}
return ptr;
} }
void port_free(void *ptr) { void port_free(void *ptr) {
@ -341,7 +344,7 @@ void *port_realloc(void *ptr, size_t size) {
} }
size_t port_heap_get_largest_free_size(void) { size_t port_heap_get_largest_free_size(void) {
size_t free_size = heap_caps_get_largest_free_block(0); size_t free_size = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT);
return free_size; return free_size;
} }

View file

@ -67,7 +67,7 @@ void PLACE_IN_ITCM(common_hal_mcu_enable_interrupts)(void) {
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
if (runmode == RUNMODE_BOOTLOADER) { if (runmode == RUNMODE_BOOTLOADER) {
if (!bootloader_available()) { if (!bootloader_available()) {
mp_raise_ValueError(MP_ERROR_TEXT("Cannot reset into bootloader because no bootloader is present")); mp_raise_ValueError(MP_ERROR_TEXT("No bootloader present"));
} }
// Pretend to be the first of the two reset presses needed to enter the // Pretend to be the first of the two reset presses needed to enter the
// bootloader. That way one reset will end in the bootloader. // bootloader. That way one reset will end in the bootloader.

View file

@ -189,7 +189,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
if (((flexpwm->MCTRL >> PWM_MCTRL_RUN_SHIFT) & sm_mask) != 0) { if (((flexpwm->MCTRL >> PWM_MCTRL_RUN_SHIFT) & sm_mask) != 0) {
// Another output has claimed this submodule for variable frequency already. // Another output has claimed this submodule for variable frequency already.
if ((_pwm_variable_frequency[flexpwm_index] & sm_mask) != 0) { if ((_pwm_variable_frequency[flexpwm_index] & sm_mask) != 0) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; return PWMOUT_INTERNAL_RESOURCES_IN_USE;
} }
// We want variable frequency but another class has already claim a fixed frequency. // We want variable frequency but another class has already claim a fixed frequency.
@ -199,7 +199,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
// Another pin is already using this output. // Another pin is already using this output.
if ((flexpwm->OUTEN & outen_mask) != 0) { if ((flexpwm->OUTEN & outen_mask) != 0) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; return PWMOUT_INTERNAL_RESOURCES_IN_USE;
} }
if (frequency != _pwm_sm_frequencies[flexpwm_index][submodule]) { if (frequency != _pwm_sm_frequencies[flexpwm_index][submodule]) {

View file

@ -30,6 +30,7 @@
#include "shared-bindings/busio/I2C.h" #include "shared-bindings/busio/I2C.h"
#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h"
#include "supervisor/shared/tick.h"
#include "py/mperrno.h" #include "py/mperrno.h"
#include "py/runtime.h" #include "py/runtime.h"
@ -39,18 +40,23 @@
// all TWI instances have the same max size // all TWI instances have the same max size
// 16 bits for 840, 10 bits for 810, 8 bits for 832 // 16 bits for 840, 10 bits for 810, 8 bits for 832
#define I2C_MAX_XFER_LEN ((1UL << TWIM0_EASYDMA_MAXCNT_SIZE) - 1) #define I2C_MAX_XFER_LEN MIN(((1UL << TWIM0_EASYDMA_MAXCNT_SIZE) - 1), 1024)
#define I2C_TIMEOUT 1000 // 1 second timeout
STATIC twim_peripheral_t twim_peripherals[] = { STATIC twim_peripheral_t twim_peripherals[] = {
#if NRFX_CHECK(NRFX_TWIM0_ENABLED) #if NRFX_CHECK(NRFX_TWIM0_ENABLED)
// SPIM0 and TWIM0 share an address. // SPIM0 and TWIM0 share an address.
{ .twim = NRFX_TWIM_INSTANCE(0), { .twim = NRFX_TWIM_INSTANCE(0),
.in_use = false}, .in_use = false,
.transferring = false,
.last_event_type = NRFX_TWIM_EVT_DONE},
#endif #endif
#if NRFX_CHECK(NRFX_TWIM1_ENABLED) #if NRFX_CHECK(NRFX_TWIM1_ENABLED)
// SPIM1 and TWIM1 share an address. // SPIM1 and TWIM1 share an address.
{ .twim = NRFX_TWIM_INSTANCE(1), { .twim = NRFX_TWIM_INSTANCE(1),
.in_use = false}, .in_use = false,
.transferring = false,
.last_event_type = NRFX_TWIM_EVT_DONE},
#endif #endif
}; };
@ -84,9 +90,12 @@ static uint8_t twi_error_to_mp(const nrfx_err_t err) {
return MP_ENODEV; return MP_ENODEV;
case NRFX_ERROR_BUSY: case NRFX_ERROR_BUSY:
return MP_EBUSY; return MP_EBUSY;
case NRFX_ERROR_DRV_TWI_ERR_DNACK:
case NRFX_ERROR_INVALID_ADDR: case NRFX_ERROR_INVALID_ADDR:
case NRFX_ERROR_DRV_TWI_ERR_DNACK:
case NRFX_ERROR_DRV_TWI_ERR_OVERRUN:
return MP_EIO; return MP_EIO;
case NRFX_ERROR_TIMEOUT:
return MP_ETIMEDOUT;
default: default:
break; break;
} }
@ -94,6 +103,13 @@ static uint8_t twi_error_to_mp(const nrfx_err_t err) {
return 0; return 0;
} }
static void twim_event_handler(nrfx_twim_evt_t const *p_event, void *p_context) {
// this is the callback handler - sets transferring to false and records the most recent event.
twim_peripheral_t *peripheral = (twim_peripheral_t *)p_context;
peripheral->last_event_type = p_event->type;
peripheral->transferring = false;
}
void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) { void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) {
if (scl->number == sda->number) { if (scl->number == sda->number) {
raise_ValueError_invalid_pins(); raise_ValueError_invalid_pins();
@ -155,7 +171,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *
// About to init. If we fail after this point, common_hal_busio_i2c_deinit() will set in_use to false. // About to init. If we fail after this point, common_hal_busio_i2c_deinit() will set in_use to false.
self->twim_peripheral->in_use = true; self->twim_peripheral->in_use = true;
nrfx_err_t err = nrfx_twim_init(&self->twim_peripheral->twim, &config, NULL, NULL); nrfx_err_t err = nrfx_twim_init(&self->twim_peripheral->twim, &config, twim_event_handler, self->twim_peripheral);
if (err != NRFX_SUCCESS) { if (err != NRFX_SUCCESS) {
common_hal_busio_i2c_deinit(self); common_hal_busio_i2c_deinit(self);
mp_raise_OSError(MP_EIO); mp_raise_OSError(MP_EIO);
@ -238,6 +254,37 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
self->has_lock = false; self->has_lock = false;
} }
STATIC nrfx_err_t _twim_xfer_with_timeout(busio_i2c_obj_t *self, nrfx_twim_xfer_desc_t const *p_xfer_desc, uint32_t flags) {
// does non-blocking transfer and raises and exception if it takes longer than I2C_TIMEOUT ms to complete
uint64_t deadline = supervisor_ticks_ms64() + I2C_TIMEOUT;
nrfx_err_t err = NRFX_SUCCESS;
self->twim_peripheral->transferring = true;
err = nrfx_twim_xfer(&self->twim_peripheral->twim, p_xfer_desc, flags);
if (err != NRFX_SUCCESS) {
self->twim_peripheral->transferring = false;
return err;
}
while (self->twim_peripheral->transferring) {
if (supervisor_ticks_ms64() > deadline) {
self->twim_peripheral->transferring = false;
return NRFX_ERROR_TIMEOUT;
}
}
switch (self->twim_peripheral->last_event_type) {
case NRFX_TWIM_EVT_DONE: ///< Transfer completed event.
return NRFX_SUCCESS;
case NRFX_TWIM_EVT_ADDRESS_NACK: ///< Error event: NACK received after sending the address.
return NRFX_ERROR_DRV_TWI_ERR_ANACK;
case NRFX_TWIM_EVT_BUS_ERROR: ///< Error event: An unexpected transition occurred on the bus.
case NRFX_TWIM_EVT_DATA_NACK: ///< Error event: NACK received after sending a data byte.
return NRFX_ERROR_DRV_TWI_ERR_DNACK;
case NRFX_TWIM_EVT_OVERRUN: ///< Error event: The unread data is replaced by new data.
return NRFX_ERROR_DRV_TWI_ERR_OVERRUN;
default: /// unknown error...
return NRFX_ERROR_INTERNAL;
}
}
STATIC uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len, bool stopBit) { STATIC uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len, bool stopBit) {
if (len == 0) { if (len == 0) {
return common_hal_busio_i2c_probe(self, addr) ? 0 : MP_ENODEV; return common_hal_busio_i2c_probe(self, addr) ? 0 : MP_ENODEV;
@ -253,7 +300,7 @@ STATIC uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
nrfx_twim_xfer_desc_t xfer_desc = NRFX_TWIM_XFER_DESC_TX(addr, (uint8_t *)data, xact_len); nrfx_twim_xfer_desc_t xfer_desc = NRFX_TWIM_XFER_DESC_TX(addr, (uint8_t *)data, xact_len);
uint32_t const flags = (stopBit ? 0 : NRFX_TWIM_FLAG_TX_NO_STOP); uint32_t const flags = (stopBit ? 0 : NRFX_TWIM_FLAG_TX_NO_STOP);
if (NRFX_SUCCESS != (err = nrfx_twim_xfer(&self->twim_peripheral->twim, &xfer_desc, flags))) { if (NRFX_SUCCESS != (err = _twim_xfer_with_timeout(self, &xfer_desc, flags))) {
break; break;
} }
@ -284,7 +331,7 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t
const size_t xact_len = MIN(len, I2C_MAX_XFER_LEN); const size_t xact_len = MIN(len, I2C_MAX_XFER_LEN);
nrfx_twim_xfer_desc_t xfer_desc = NRFX_TWIM_XFER_DESC_RX(addr, data, xact_len); nrfx_twim_xfer_desc_t xfer_desc = NRFX_TWIM_XFER_DESC_RX(addr, data, xact_len);
if (NRFX_SUCCESS != (err = nrfx_twim_xfer(&self->twim_peripheral->twim, &xfer_desc, 0))) { if (NRFX_SUCCESS != (err = _twim_xfer_with_timeout(self, &xfer_desc, 0))) {
break; break;
} }

View file

@ -34,6 +34,9 @@
typedef struct { typedef struct {
nrfx_twim_t twim; nrfx_twim_t twim;
bool in_use; bool in_use;
volatile bool transferring;
nrfx_twim_evt_type_t last_event_type;
uint32_t timeout;
} twim_peripheral_t; } twim_peripheral_t;
typedef struct { typedef struct {

View file

@ -220,7 +220,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
&channel, &pwm_already_in_use, NULL); &channel, &pwm_already_in_use, NULL);
if (self->pwm == NULL) { if (self->pwm == NULL) {
return PWMOUT_ALL_TIMERS_IN_USE; return PWMOUT_INTERNAL_RESOURCES_IN_USE;
} }
self->channel = channel; self->channel = channel;

@ -1 +1 @@
Subproject commit 3f55e49eb11e6db0da1da09e189bb094222702c9 Subproject commit ab21106ea57b63d97b757a9f17201ddf298ffab0

View file

@ -0,0 +1,114 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "supervisor/board.h"
#include "mpconfigboard.h"
#include "shared-bindings/busio/SPI.h"
#include "shared-bindings/fourwire/FourWire.h"
#include "shared-module/displayio/__init__.h"
#include "shared-module/displayio/mipi_constants.h"
#include "supervisor/shared/board.h"
fourwire_fourwire_obj_t board_display_obj;
#define DELAY 0x80
uint8_t display_init_sequence[] = {
0x01, 0 | DELAY, 150, // SWRESET
0x36, 1, 0x04, // MADCTL
0x35, 1, 0x00, // TEON
0xB2, 5, 0x0c, 0x0c, 0x00, 0x33, 0x33, // FRMCTR2
0x3A, 1, 0x05, // COLMOD
0xB7, 1, 0x14, // GCTRL
0xBB, 1, 0x37, // VCOMS
0xC0, 1, 0x2c, // LCMCTRL
0xC2, 1, 0x01, // VDVVRHEN
0xC3, 1, 0x12, // VRHS
0xC4, 1, 0x20, // VDVS
0xD0, 2, 0xa4, 0xa1, // PWRCTRL1
0xC6, 1, 0x0f, // FRCTRL2
0xE0, 14, 0xd0, 0x04, 0x0d, 0x11, 0x13, 0x2b, 0x3f, 0x54, 0x4c, 0x18, 0x0d, 0x0b, 0x1f, 0x23, // GMCTRP1
0xE1, 14, 0xd0, 0x04, 0x0c, 0x11, 0x13, 0x2c, 0x3f, 0x44, 0x51, 0x2f, 0x1f, 0x1f, 0x20, 0x23, // GMCTRN1
0x21, 0, // INVON
0x11, 0 | DELAY, 255, // SLPOUT
0x29, 0 | DELAY, 100, // DISPON
0x2a, 4, 0x00, 0, 0x00, 0xfe, // CASET
0x2b, 4, 0x00, 0, 0x00, 0xfe, // RASET
0x2c, 0, // RAMWR
};
void board_init(void) {
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
busio_spi_obj_t *spi = &bus->inline_bus;
common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO19, NULL, false);
common_hal_busio_spi_never_reset(spi);
bus->base.type = &fourwire_fourwire_type;
common_hal_fourwire_fourwire_construct(bus,
spi,
&pin_GPIO16, // TFT_DC Command or data
&pin_GPIO17, // TFT_CS Chip select
NULL, // TFT_RST Reset
62500000, // Baudrate
0, // Polarity
0); // Phase
busdisplay_busdisplay_obj_t *display = &allocate_display()->display;
display->base.type = &busdisplay_busdisplay_type;
common_hal_busdisplay_busdisplay_construct(display,
bus,
240, // Width
280, // Height
0, // column start
20, // row start
0, // rotation
16, // Color depth
false, // Grayscale
false, // pixels in a byte share a row. Only valid for depths < 8
1, // bytes per cell. Only valid for depths < 8
false, // reverse_pixels_in_byte. Only valid for depths < 8
true, // reverse_bytes_in_word
MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
display_init_sequence,
sizeof(display_init_sequence),
NULL, // no backlight pin
NO_BRIGHTNESS_COMMAND,
1.0f, // brightness
false, // single_byte_bounds
false, // data_as_commands
true, // auto_refresh
60, // native_frames_per_second
true, // backlight_on_high
false, // SH1107_addressing
0); // backlight pwm frequency
}
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.

View file

@ -0,0 +1,12 @@
#define MICROPY_HW_BOARD_NAME "HEIA-FR Picomo V2"
#define MICROPY_HW_MCU_NAME "rp2040"
#define CIRCUITPY_RGB_STATUS_R (&pin_GPIO10)
#define CIRCUITPY_RGB_STATUS_G (&pin_GPIO9)
#define CIRCUITPY_RGB_STATUS_B (&pin_GPIO8)
#define DEFAULT_I2C_BUS_SCL (&pin_GPIO21)
#define DEFAULT_I2C_BUS_SDA (&pin_GPIO20)
#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18)
#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19)

View file

@ -0,0 +1,18 @@
USB_VID = 0x2E8A
USB_PID = 0x107D
USB_PRODUCT = "Picomo V2"
USB_MANUFACTURER = "HEIA-FR"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2
EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ"
CIRCUITPY__EVE = 1
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ST7789
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Shapes
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Text
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ProgressBar

View file

@ -0,0 +1 @@
// Put board-specific pico-sdk definitions here. This file must exist.

View file

@ -0,0 +1,99 @@
#include "shared-bindings/board/__init__.h"
#include "shared-module/displayio/__init__.h"
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
{ MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_SW_UP), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_S1), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_SW_MID), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_S5), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_SW_DOWN), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_S2), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_SW_TOPR), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_BOOTSEL), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_S7), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_SW_RIGHT), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_S4), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_BUZZER), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_DISP_DC), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_DISP_CS), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_DISP_SCL), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_DISP_SDA), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_TEMP_SDA), MP_ROM_PTR(&pin_GPIO20) },
{ MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) },
{ MP_ROM_QSTR(MP_QSTR_TEMP_SCL), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_SW_LEFT), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_S3), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_SW_TOPL), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_S6), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_USB_OVCUR), MP_ROM_PTR(&pin_GPIO24) },
{ MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) },
{ MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) },
{ MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)},
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View file

@ -119,21 +119,21 @@ pwmout_result_t pwmout_allocate(uint8_t slice, uint8_t ab_channel, bool variable
// Check the channel first. // Check the channel first.
if ((channel_use & channel_use_mask) != 0) { if ((channel_use & channel_use_mask) != 0) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; return PWMOUT_INTERNAL_RESOURCES_IN_USE;
} }
// Now check if the slice is in use and if we can share with it. // Now check if the slice is in use and if we can share with it.
if (target_slice_frequencies[slice] > 0) { if (target_slice_frequencies[slice] > 0) {
// If we want to change frequency then we can't share. // If we want to change frequency then we can't share.
if (variable_frequency) { if (variable_frequency) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; return PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE;
} }
// If the other user wants a variable frequency then we can't share either. // If the other user wants a variable frequency then we can't share either.
if ((slice_variable_frequency & (1 << slice)) != 0) { if ((slice_variable_frequency & (1 << slice)) != 0) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; return PWMOUT_INTERNAL_RESOURCES_IN_USE;
} }
// If we're both fixed frequency but we don't match target frequencies then we can't share. // If we're both fixed frequency but we don't match target frequencies then we can't share.
if (target_slice_frequencies[slice] != frequency) { if (target_slice_frequencies[slice] != frequency) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; return PWMOUT_INVALID_FREQUENCY_ON_PIN;
} }
} }

View file

@ -83,7 +83,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
} }
if (self->tim == NULL) { if (self->tim == NULL) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; return PWMOUT_INTERNAL_RESOURCES_IN_USE;
} }
self->duty_cycle = duty; self->duty_cycle = duty;

View file

@ -26,3 +26,9 @@ MCU_PACKAGE = UFQFPN48
LD_COMMON = boards/common_nvm.ld LD_COMMON = boards/common_nvm.ld
LD_FILE = boards/STM32F411_nvm_nofs.ld LD_FILE = boards/STM32F411_nvm_nofs.ld
# Disable TERMINALIO on translations with missing characters.
ifneq (,$(filter $(TRANSLATION),ja ko ru))
CIRCUITPY_TERMINALIO = 0
RELEASE_NEEDS_CLEAN_BUILD = $(CIRCUITPY_DISPLAYIO)
endif

View file

@ -110,12 +110,12 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
if (tim_index < TIM_BANK_ARRAY_LEN && tim_channels_taken[tim_index] != 0) { if (tim_index < TIM_BANK_ARRAY_LEN && tim_channels_taken[tim_index] != 0) {
// Timer has already been reserved by an internal module // Timer has already been reserved by an internal module
if (stm_peripherals_timer_is_reserved(mcu_tim_banks[tim_index])) { if (stm_peripherals_timer_is_reserved(mcu_tim_banks[tim_index])) {
last_failure = PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; last_failure = PWMOUT_INTERNAL_RESOURCES_IN_USE;
continue; // keep looking continue; // keep looking
} }
// is it the same channel? (or all channels reserved by a var-freq) // is it the same channel? (or all channels reserved by a var-freq)
if (tim_channels_taken[tim_index] & (1 << tim_channel_index)) { if (tim_channels_taken[tim_index] & (1 << tim_channel_index)) {
last_failure = PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; last_failure = PWMOUT_INTERNAL_RESOURCES_IN_USE;
continue; // keep looking, might be another viable option continue; // keep looking, might be another viable option
} }
// If the frequencies are the same it's ok // If the frequencies are the same it's ok

View file

@ -87,7 +87,7 @@ extern void common_hal_mcu_enable_interrupts(void);
#define MICROPY_TRACKED_ALLOC (CIRCUITPY_SSL_MBEDTLS) #define MICROPY_TRACKED_ALLOC (CIRCUITPY_SSL_MBEDTLS)
#define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_ENABLE_SOURCE_LINE (1)
#define MICROPY_EPOCH_IS_1970 (1) #define MICROPY_EPOCH_IS_1970 (1)
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) #define MICROPY_ERROR_REPORTING (CIRCUITPY_FULL_BUILD ? MICROPY_ERROR_REPORTING_NORMAL : MICROPY_ERROR_REPORTING_TERSE)
#define MICROPY_FLOAT_HIGH_QUALITY_HASH (0) #define MICROPY_FLOAT_HIGH_QUALITY_HASH (0)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
#define MICROPY_GC_ALLOC_THRESHOLD (0) #define MICROPY_GC_ALLOC_THRESHOLD (0)

View file

@ -49,6 +49,22 @@ const mp_obj_dict_t mp_const_empty_dict_obj = {
} }
}; };
// CIRCUITPY-CHANGE: Native methods are passed the subclass instance so they can
// refer to subclass members. Dict only cares about the native struct so this
// function gets it.
STATIC mp_obj_dict_t *native_dict(mp_obj_t self_in) {
// Check for OrderedDict first because it is marked as a subclass of dict. However, it doesn't
// store its state in subobj like python types to native types do.
mp_obj_t native_instance = MP_OBJ_NULL;
#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
native_instance = mp_obj_cast_to_native_base(self_in, MP_OBJ_FROM_PTR(&mp_type_ordereddict));
#endif
if (native_instance == MP_OBJ_NULL) {
native_instance = mp_obj_cast_to_native_base(self_in, MP_OBJ_FROM_PTR(&mp_type_dict));
}
return MP_OBJ_TO_PTR(native_instance);
}
STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs); STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
// This is a helper function to iterate through a dictionary. The state of // This is a helper function to iterate through a dictionary. The state of
@ -71,7 +87,7 @@ STATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, size_t *cur) {
} }
STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_dict_t *self = native_dict(self_in);
bool first = true; bool first = true;
const char *item_separator = ", "; const char *item_separator = ", ";
const char *key_separator = ": "; const char *key_separator = ": ";
@ -144,7 +160,7 @@ mp_obj_t mp_obj_dict_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
} }
STATIC mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) { STATIC mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_dict_t *self = native_dict(self_in);
switch (op) { switch (op) {
case MP_UNARY_OP_BOOL: case MP_UNARY_OP_BOOL:
return mp_obj_new_bool(self->map.used != 0); return mp_obj_new_bool(self->map.used != 0);
@ -162,7 +178,7 @@ STATIC mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
} }
STATIC mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { STATIC mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_dict_t *o = MP_OBJ_TO_PTR(lhs_in); mp_obj_dict_t *o = native_dict(lhs_in);
switch (op) { switch (op) {
case MP_BINARY_OP_CONTAINS: { case MP_BINARY_OP_CONTAINS: {
mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP); mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
@ -223,7 +239,7 @@ STATIC mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_
// Note: Make sure this is inlined in load part of dict_subscr() below. // Note: Make sure this is inlined in load part of dict_subscr() below.
mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index) { mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index) {
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_dict_t *self = native_dict(self_in);
mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP); mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP);
if (elem == NULL) { if (elem == NULL) {
mp_raise_type_arg(&mp_type_KeyError, index); mp_raise_type_arg(&mp_type_KeyError, index);
@ -239,7 +255,7 @@ STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
return mp_const_none; return mp_const_none;
} else if (value == MP_OBJ_SENTINEL) { } else if (value == MP_OBJ_SENTINEL) {
// load // load
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_dict_t *self = native_dict(self_in);
mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP); mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP);
if (elem == NULL) { if (elem == NULL) {
mp_raise_type_arg(&mp_type_KeyError, index); mp_raise_type_arg(&mp_type_KeyError, index);
@ -264,7 +280,7 @@ STATIC void PLACE_IN_ITCM(mp_ensure_not_fixed)(const mp_obj_dict_t * dict) {
STATIC mp_obj_t dict_clear(mp_obj_t self_in) { STATIC mp_obj_t dict_clear(mp_obj_t self_in) {
mp_check_self(mp_obj_is_dict_or_ordereddict(self_in)); mp_check_self(mp_obj_is_dict_or_ordereddict(self_in));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_dict_t *self = native_dict(self_in);
mp_ensure_not_fixed(self); mp_ensure_not_fixed(self);
mp_map_clear(&self->map); mp_map_clear(&self->map);
@ -275,9 +291,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_clear_obj, dict_clear);
mp_obj_t mp_obj_dict_copy(mp_obj_t self_in) { mp_obj_t mp_obj_dict_copy(mp_obj_t self_in) {
mp_check_self(mp_obj_is_dict_or_ordereddict(self_in)); mp_check_self(mp_obj_is_dict_or_ordereddict(self_in));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_dict_t *self = native_dict(self_in);
mp_obj_t other_out = mp_obj_new_dict(self->map.alloc); mp_obj_t other_out = mp_obj_new_dict(self->map.alloc);
mp_obj_dict_t *other = MP_OBJ_TO_PTR(other_out); mp_obj_dict_t *other = native_dict(other_out);
other->base.type = self->base.type; other->base.type = self->base.type;
other->map.used = self->map.used; other->map.used = self->map.used;
other->map.all_keys_are_qstrs = self->map.all_keys_are_qstrs; other->map.all_keys_are_qstrs = self->map.all_keys_are_qstrs;
@ -324,7 +340,7 @@ STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(dict_fromkeys_obj, MP_ROM_PTR(&dict_fromk
STATIC mp_obj_t dict_get_helper(size_t n_args, const mp_obj_t *args, mp_map_lookup_kind_t lookup_kind) { STATIC mp_obj_t dict_get_helper(size_t n_args, const mp_obj_t *args, mp_map_lookup_kind_t lookup_kind) {
mp_check_self(mp_obj_is_dict_or_ordereddict(args[0])); mp_check_self(mp_obj_is_dict_or_ordereddict(args[0]));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_dict_t *self = native_dict(args[0]);
if (lookup_kind != MP_MAP_LOOKUP) { if (lookup_kind != MP_MAP_LOOKUP) {
mp_ensure_not_fixed(self); mp_ensure_not_fixed(self);
} }
@ -369,7 +385,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setde
STATIC mp_obj_t dict_popitem(mp_obj_t self_in) { STATIC mp_obj_t dict_popitem(mp_obj_t self_in) {
mp_check_self(mp_obj_is_dict_or_ordereddict(self_in)); mp_check_self(mp_obj_is_dict_or_ordereddict(self_in));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_dict_t *self = native_dict(self_in);
mp_ensure_not_fixed(self); mp_ensure_not_fixed(self);
if (self->map.used == 0) { if (self->map.used == 0) {
mp_raise_msg_varg(&mp_type_KeyError, MP_ERROR_TEXT("pop from empty %q"), MP_QSTR_dict); mp_raise_msg_varg(&mp_type_KeyError, MP_ERROR_TEXT("pop from empty %q"), MP_QSTR_dict);
@ -394,7 +410,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem);
STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
mp_check_self(mp_obj_is_dict_or_ordereddict(args[0])); mp_check_self(mp_obj_is_dict_or_ordereddict(args[0]));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_dict_t *self = native_dict(args[0]);
mp_ensure_not_fixed(self); mp_ensure_not_fixed(self);
mp_arg_check_num(n_args, kwargs->used, 1, 2, true); mp_arg_check_num(n_args, kwargs->used, 1, 2, true);
@ -520,7 +536,7 @@ typedef struct _mp_obj_dict_view_t {
STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) { STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
mp_check_self(mp_obj_is_type(self_in, &mp_type_dict_view_it)); mp_check_self(mp_obj_is_type(self_in, &mp_type_dict_view_it));
mp_obj_dict_view_it_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_dict_view_it_t *self = MP_OBJ_TO_PTR(self_in);
mp_map_elem_t *next = dict_iter_next(MP_OBJ_TO_PTR(self->dict), &self->cur); mp_map_elem_t *next = dict_iter_next(native_dict(self->dict), &self->cur);
if (next == NULL) { if (next == NULL) {
return MP_OBJ_STOP_ITERATION; return MP_OBJ_STOP_ITERATION;
@ -726,7 +742,7 @@ size_t mp_obj_dict_len(mp_obj_t self_in) {
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) { mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) {
mp_check_self(mp_obj_is_dict_or_ordereddict(self_in)); mp_check_self(mp_obj_is_dict_or_ordereddict(self_in));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_dict_t *self = native_dict(self_in);
mp_ensure_not_fixed(self); mp_ensure_not_fixed(self);
mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
return self_in; return self_in;

View file

@ -140,9 +140,9 @@ mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
if (u.p.exp == ((1 << MP_FLOAT_EXP_BITS) - 1)) { if (u.p.exp == ((1 << MP_FLOAT_EXP_BITS) - 1)) {
// ...then number is Inf (positive or negative) if fraction is 0, else NaN. // ...then number is Inf (positive or negative) if fraction is 0, else NaN.
if (u.p.frc == 0) { if (u.p.frc == 0) {
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("can't convert inf to int")); mp_raise_msg_varg(&mp_type_OverflowError, MP_ERROR_TEXT("can't convert %s to int"), "inf");
} else { } else {
mp_raise_ValueError(MP_ERROR_TEXT("can't convert NaN to int")); mp_raise_ValueError_varg(MP_ERROR_TEXT("can't convert %s to int"), "NaN");
} }
} else { } else {
mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val); mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);

View file

@ -27,22 +27,26 @@
#include "py/obj.h" #include "py/obj.h"
#include "py/builtin.h" #include "py/builtin.h"
// CIRCUITPY-CHANGE: These three functions are used by dict only. In CP, we hard
// code the type to dict so that subclassed types still use the native dict
// subscr. MP doesn't have this problem because it passes the native instance
// in. CP passes the subclass instance.
STATIC mp_obj_t op_getitem(mp_obj_t self_in, mp_obj_t key_in) { STATIC mp_obj_t op_getitem(mp_obj_t self_in, mp_obj_t key_in) {
const mp_obj_type_t *type = mp_obj_get_type(self_in); const mp_obj_type_t *type = &mp_type_dict;
// Note: assumes type must have subscr (only used by dict). // Note: assumes type must have subscr (only used by dict).
return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, MP_OBJ_SENTINEL); return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, MP_OBJ_SENTINEL);
} }
MP_DEFINE_CONST_FUN_OBJ_2(mp_op_getitem_obj, op_getitem); MP_DEFINE_CONST_FUN_OBJ_2(mp_op_getitem_obj, op_getitem);
STATIC mp_obj_t op_setitem(mp_obj_t self_in, mp_obj_t key_in, mp_obj_t value_in) { STATIC mp_obj_t op_setitem(mp_obj_t self_in, mp_obj_t key_in, mp_obj_t value_in) {
const mp_obj_type_t *type = mp_obj_get_type(self_in); const mp_obj_type_t *type = &mp_type_dict;
// Note: assumes type must have subscr (only used by dict). // Note: assumes type must have subscr (only used by dict).
return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, value_in); return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, value_in);
} }
MP_DEFINE_CONST_FUN_OBJ_3(mp_op_setitem_obj, op_setitem); MP_DEFINE_CONST_FUN_OBJ_3(mp_op_setitem_obj, op_setitem);
STATIC mp_obj_t op_delitem(mp_obj_t self_in, mp_obj_t key_in) { STATIC mp_obj_t op_delitem(mp_obj_t self_in, mp_obj_t key_in) {
const mp_obj_type_t *type = mp_obj_get_type(self_in); const mp_obj_type_t *type = &mp_type_dict;
// Note: assumes type must have subscr (only used by dict). // Note: assumes type must have subscr (only used by dict).
return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, MP_OBJ_NULL); return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, MP_OBJ_NULL);
} }

View file

@ -1095,12 +1095,7 @@ STATIC mp_obj_t checked_fun_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c
if (n_args > 0) { if (n_args > 0) {
const mp_obj_type_t *arg0_type = mp_obj_get_type(args[0]); const mp_obj_type_t *arg0_type = mp_obj_get_type(args[0]);
if (arg0_type != self->type) { if (arg0_type != self->type) {
#if MICROPY_ERROR_REPORTING != MICROPY_ERROR_REPORTING_DETAILED mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q, not %q"), MP_QSTR_self, self->type->name, arg0_type->name);
mp_raise_TypeError(MP_ERROR_TEXT("argument has wrong type"));
#else
mp_raise_msg_varg(&mp_type_TypeError,
MP_ERROR_TEXT("argument should be a '%q' not a '%q'"), self->type->name, arg0_type->name);
#endif
} }
} }
return mp_call_function_n_kw(self->fun, n_args, n_kw, args); return mp_call_function_n_kw(self->fun, n_args, n_kw, args);

View file

@ -134,7 +134,7 @@ STATIC mp_obj_t bitmapfilter_morph(size_t n_args, const mp_obj_t *pos_args, mp_m
mp_obj_t weights = args[ARG_weights].u_obj; mp_obj_t weights = args[ARG_weights].u_obj;
mp_obj_t obj_len = mp_obj_len(weights); mp_obj_t obj_len = mp_obj_len(weights);
if (obj_len == MP_OBJ_NULL || !mp_obj_is_small_int(obj_len)) { if (obj_len == MP_OBJ_NULL || !mp_obj_is_small_int(obj_len)) {
mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be of type %q, not %q"), MP_QSTR_weights, MP_QSTR_Sequence, mp_obj_get_type(weights)->name); mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be of type %q, not %q"), MP_QSTR_weights, MP_QSTR_Sequence, mp_obj_get_type_qstr(weights));
} }
size_t n_weights = MP_OBJ_SMALL_INT_VALUE(obj_len); size_t n_weights = MP_OBJ_SMALL_INT_VALUE(obj_len);
@ -608,8 +608,131 @@ STATIC mp_obj_t bitmapfilter_false_color(size_t n_args, const mp_obj_t *pos_args
shared_module_bitmapfilter_false_color(bitmap, mask, palette->colors); shared_module_bitmapfilter_false_color(bitmap, mask, palette->colors);
return args[ARG_bitmap].u_obj; return args[ARG_bitmap].u_obj;
} }
MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_false_color_obj, 0, bitmapfilter_false_color); MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_false_color_obj, 0, bitmapfilter_false_color);
#define BLEND_TABLE_SIZE (4096)
STATIC uint8_t *get_blend_table(mp_obj_t lookup, int mode) {
mp_buffer_info_t lookup_buf;
if (!mp_get_buffer(lookup, &lookup_buf, mode) || lookup_buf.len != BLEND_TABLE_SIZE) {
return NULL;
}
return lookup_buf.buf;
}
//|
//| BlendFunction = Callable[[float, float], float]
//| """A function used to blend two images"""
//|
//| BlendTable = bytearray
//| """A precomputed blend table
//|
//| There is not actually a BlendTable type. The real type is actually any
//| buffer 4096 bytes in length."""
//|
//| def blend_precompute(lookup: BlendFunction, table: BlendTable | None = None) -> BlendTable:
//| """Precompute a BlendTable from a BlendFunction
//|
//| If the optional ``table`` argument is provided, an existing `BlendTable` is updated
//| with the new function values.
//|
//| The function's two arguments will range from 0 to 1. The returned value should also range from 0 to 1.
//|
//| A function to do a 33% blend of each source image could look like this:
//|
//| .. code-block:: python
//|
//| def blend_one_third(a, b):
//| return a * .33 + b * .67
//| """
//|
STATIC mp_obj_t blend_precompute(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_lookup, ARG_table };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_lookup, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
{ MP_QSTR_table, MP_ARG_OBJ, { .u_obj = MP_ROM_NONE } },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_obj_t table = args[ARG_table].u_obj;
if (table == mp_const_none) {
table = mp_obj_new_bytearray_of_zeros(BLEND_TABLE_SIZE);
}
uint8_t *buf = get_blend_table(table, MP_BUFFER_WRITE);
if (!buf) {
mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q or %q, not %q"),
MP_QSTR_table, MP_QSTR_NoneType, MP_QSTR_WritableBuffer,
mp_obj_get_type_qstr(table));
}
shared_module_bitmapfilter_blend_precompute(args[ARG_lookup].u_obj, buf);
return table;
}
MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_blend_precompute_obj, 0, blend_precompute);
//|
//| def blend(
//| dest: displayio.Bitmap,
//| src1: displayio.Bitmap,
//| src2: displayio.Bitmap,
//| lookup: BlendFunction | BlendTable,
//| mask: displayio.Bitmap | None = None,
//| ) -> displayio.Bitmap:
//| """Blend the 'src1' and 'src2' images according to lookup function or table 'lookup'
//|
//| If ``lookup`` is a function, it is converted to a `BlendTable` by
//| internally calling blend_precompute. If a blend function is used repeatedly
//| it can be more efficient to compute it once with `blend_precompute`.
//|
//| If the mask is supplied, pixels from ``src1`` are taken unchanged in masked areas.
//|
//| The source and destination bitmaps may be the same bitmap.
//|
//| The destination bitmap is returned.
//| """
//|
STATIC mp_obj_t bitmapfilter_blend(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_dest, ARG_src1, ARG_src2, ARG_lookup, ARG_mask };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_dest, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
{ MP_QSTR_src1, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
{ MP_QSTR_src2, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
{ MP_QSTR_lookup, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
{ MP_QSTR_mask, MP_ARG_OBJ, { .u_obj = MP_ROM_NONE } },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_arg_validate_type(args[ARG_dest].u_obj, &displayio_bitmap_type, MP_QSTR_dest);
displayio_bitmap_t *dest = MP_OBJ_TO_PTR(args[ARG_dest].u_obj);
mp_arg_validate_type(args[ARG_src1].u_obj, &displayio_bitmap_type, MP_QSTR_src1);
displayio_bitmap_t *src1 = MP_OBJ_TO_PTR(args[ARG_src1].u_obj);
mp_arg_validate_type(args[ARG_src2].u_obj, &displayio_bitmap_type, MP_QSTR_src2);
displayio_bitmap_t *src2 = MP_OBJ_TO_PTR(args[ARG_src2].u_obj);
mp_obj_t lookup = args[ARG_lookup].u_obj;
if (mp_obj_is_callable(lookup)) {
lookup = mp_call_function_1(MP_OBJ_FROM_PTR(&bitmapfilter_blend_precompute_obj), lookup);
}
uint8_t *lookup_buf = get_blend_table(lookup, MP_BUFFER_READ);
if (!lookup_buf) {
mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q or %q, not %q"),
MP_QSTR_lookup, MP_QSTR_callable, MP_QSTR_ReadableBuffer,
mp_obj_get_type_qstr(lookup));
}
displayio_bitmap_t *mask = NULL;
if (args[ARG_mask].u_obj != mp_const_none) {
mp_arg_validate_type(args[ARG_mask].u_obj, &displayio_bitmap_type, MP_QSTR_mask);
mask = MP_OBJ_TO_PTR(args[ARG_mask].u_obj);
}
shared_module_bitmapfilter_blend(dest, src1, src2, mask, lookup_buf);
return args[ARG_dest].u_obj;
}
MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_blend_obj, 0, bitmapfilter_blend);
STATIC const mp_rom_map_elem_t bitmapfilter_module_globals_table[] = { STATIC const mp_rom_map_elem_t bitmapfilter_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bitmapfilter) }, { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bitmapfilter) },
{ MP_ROM_QSTR(MP_QSTR_morph), MP_ROM_PTR(&bitmapfilter_morph_obj) }, { MP_ROM_QSTR(MP_QSTR_morph), MP_ROM_PTR(&bitmapfilter_morph_obj) },
@ -621,6 +744,8 @@ STATIC const mp_rom_map_elem_t bitmapfilter_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_ChannelScaleOffset), MP_ROM_PTR(&bitmapfilter_channel_scale_offset_type) }, { MP_ROM_QSTR(MP_QSTR_ChannelScaleOffset), MP_ROM_PTR(&bitmapfilter_channel_scale_offset_type) },
{ MP_ROM_QSTR(MP_QSTR_ChannelMixer), MP_ROM_PTR(&bitmapfilter_channel_mixer_type) }, { MP_ROM_QSTR(MP_QSTR_ChannelMixer), MP_ROM_PTR(&bitmapfilter_channel_mixer_type) },
{ MP_ROM_QSTR(MP_QSTR_ChannelMixerOffset), MP_ROM_PTR(&bitmapfilter_channel_mixer_offset_type) }, { MP_ROM_QSTR(MP_QSTR_ChannelMixerOffset), MP_ROM_PTR(&bitmapfilter_channel_mixer_offset_type) },
{ MP_ROM_QSTR(MP_QSTR_blend), MP_ROM_PTR(&bitmapfilter_blend_obj) },
{ MP_ROM_QSTR(MP_QSTR_blend_precompute), MP_ROM_PTR(&bitmapfilter_blend_precompute_obj) },
}; };
STATIC MP_DEFINE_CONST_DICT(bitmapfilter_module_globals, bitmapfilter_module_globals_table); STATIC MP_DEFINE_CONST_DICT(bitmapfilter_module_globals, bitmapfilter_module_globals_table);

View file

@ -73,3 +73,12 @@ void shared_module_bitmapfilter_false_color(
displayio_bitmap_t *bitmap, displayio_bitmap_t *bitmap,
displayio_bitmap_t *mask, displayio_bitmap_t *mask,
_displayio_color_t palette[256]); _displayio_color_t palette[256]);
void shared_module_bitmapfilter_blend_precompute(mp_obj_t fun, uint8_t lookup[4096]);
void shared_module_bitmapfilter_blend(
displayio_bitmap_t *dest,
displayio_bitmap_t *src1,
displayio_bitmap_t *src2,
displayio_bitmap_t *mask,
const uint8_t lookup[4096]);

View file

@ -1063,10 +1063,10 @@ STATIC mp_obj_t bitmaptools_obj_blit(size_t n_args, const mp_obj_t *pos_args, mp
uint16_t x = mp_arg_validate_int_range(args[ARG_x].u_int, 0, destination->width, MP_QSTR_x); uint16_t x = mp_arg_validate_int_range(args[ARG_x].u_int, 0, destination->width, MP_QSTR_x);
uint16_t y = mp_arg_validate_int_range(args[ARG_y].u_int, 0, destination->height, MP_QSTR_y); uint16_t y = mp_arg_validate_int_range(args[ARG_y].u_int, 0, destination->height, MP_QSTR_y);
bitmaptools_rect_t lim = bitmaptools_validate_coord_range_pair(&args[ARG_x1], destination->width, destination->height);
displayio_bitmap_t *source = mp_arg_validate_type(args[ARG_source].u_obj, &displayio_bitmap_type, MP_QSTR_source_bitmap); displayio_bitmap_t *source = mp_arg_validate_type(args[ARG_source].u_obj, &displayio_bitmap_type, MP_QSTR_source_bitmap);
bitmaptools_rect_t lim = bitmaptools_validate_coord_range_pair(&args[ARG_x1], source->width, source->height);
// ensure that the target bitmap (self) has at least as many `bits_per_value` as the source // ensure that the target bitmap (self) has at least as many `bits_per_value` as the source
if (destination->bits_per_value < source->bits_per_value) { if (destination->bits_per_value < source->bits_per_value) {

View file

@ -46,23 +46,17 @@ void common_hal_pwmio_pwmout_raise_error(pwmout_result_t result) {
mp_arg_error_invalid(MP_QSTR_frequency); mp_arg_error_invalid(MP_QSTR_frequency);
break; break;
case PWMOUT_INVALID_FREQUENCY_ON_PIN: case PWMOUT_INVALID_FREQUENCY_ON_PIN:
mp_raise_ValueError(MP_ERROR_TEXT("Frequency must match existing PWMOut using this timer")); mp_arg_error_invalid(MP_QSTR_frequency);
break; break;
case PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE: case PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE:
mp_raise_ValueError(MP_ERROR_TEXT("Cannot vary frequency on a timer that is already in use")); mp_arg_error_invalid(MP_QSTR_variable_frequency);
break; break;
case PWMOUT_ALL_TIMERS_ON_PIN_IN_USE: case PWMOUT_INTERNAL_RESOURCES_IN_USE:
mp_raise_ValueError(MP_ERROR_TEXT("All timers for this pin are in use")); mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
break;
case PWMOUT_ALL_TIMERS_IN_USE:
mp_raise_RuntimeError(MP_ERROR_TEXT("All timers in use"));
break;
case PWMOUT_ALL_CHANNELS_IN_USE:
mp_raise_RuntimeError(MP_ERROR_TEXT("All channels in use"));
break; break;
default: default:
case PWMOUT_INITIALIZATION_ERROR: case PWMOUT_INITIALIZATION_ERROR:
mp_raise_RuntimeError(MP_ERROR_TEXT("Could not start PWM")); mp_raise_RuntimeError(MP_ERROR_TEXT("Internal error"));
break; break;
} }
} }
@ -268,8 +262,7 @@ STATIC mp_obj_t pwmio_pwmout_obj_set_frequency(mp_obj_t self_in, mp_obj_t freque
pwmio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in); pwmio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self); check_for_deinit(self);
if (!common_hal_pwmio_pwmout_get_variable_frequency(self)) { if (!common_hal_pwmio_pwmout_get_variable_frequency(self)) {
mp_raise_AttributeError(MP_ERROR_TEXT( mp_raise_msg_varg(&mp_type_AttributeError, MP_ERROR_TEXT("Invalid %q"), MP_QSTR_variable_frequency);
"PWM frequency not writable when variable_frequency is False on construction."));
} }
mp_int_t freq = mp_obj_get_int(frequency); mp_int_t freq = mp_obj_get_int(frequency);
if (freq == 0) { if (freq == 0) {

View file

@ -38,9 +38,7 @@ typedef enum pwmout_result_t {
PWMOUT_INVALID_FREQUENCY, PWMOUT_INVALID_FREQUENCY,
PWMOUT_INVALID_FREQUENCY_ON_PIN, PWMOUT_INVALID_FREQUENCY_ON_PIN,
PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE, PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE,
PWMOUT_ALL_TIMERS_ON_PIN_IN_USE, PWMOUT_INTERNAL_RESOURCES_IN_USE,
PWMOUT_ALL_TIMERS_IN_USE,
PWMOUT_ALL_CHANNELS_IN_USE,
PWMOUT_INITIALIZATION_ERROR, PWMOUT_INITIALIZATION_ERROR,
} pwmout_result_t; } pwmout_result_t;

View file

@ -131,7 +131,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_deinit_obj, sdcardio_sdcard_deinit);
//| //|
//| :return: None""" //| :return: None"""
STATIC mp_obj_t sdcardio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) { STATIC mp_obj_t _sdcardio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
uint32_t start_block = mp_obj_get_int(start_block_in); uint32_t start_block = mp_obj_get_int(start_block_in);
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
@ -143,7 +143,7 @@ STATIC mp_obj_t sdcardio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_bloc
return mp_const_none; return mp_const_none;
} }
MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_readblocks_obj, sdcardio_sdcard_readblocks); MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_readblocks_obj, _sdcardio_sdcard_readblocks);
//| def sync(self) -> None: //| def sync(self) -> None:
//| """Ensure all blocks written are actually committed to the SD card //| """Ensure all blocks written are actually committed to the SD card
@ -171,7 +171,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_sync_obj, sdcardio_sdcard_sync);
//| :return: None""" //| :return: None"""
//| //|
STATIC mp_obj_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) { STATIC mp_obj_t _sdcardio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
uint32_t start_block = mp_obj_get_int(start_block_in); uint32_t start_block = mp_obj_get_int(start_block_in);
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
@ -182,7 +182,7 @@ STATIC mp_obj_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_blo
} }
return mp_const_none; return mp_const_none;
} }
MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_writeblocks_obj, sdcardio_sdcard_writeblocks); MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_writeblocks_obj, _sdcardio_sdcard_writeblocks);
STATIC const mp_rom_map_elem_t sdcardio_sdcard_locals_dict_table[] = { STATIC const mp_rom_map_elem_t sdcardio_sdcard_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&sdcardio_sdcard_count_obj) }, { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&sdcardio_sdcard_count_obj) },

View file

@ -27,4 +27,19 @@
#pragma once #pragma once
#include "shared-module/sdcardio/SDCard.h"
extern const mp_obj_type_t sdcardio_SDCard_type; extern const mp_obj_type_t sdcardio_SDCard_type;
void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *spi, const mcu_pin_obj_t *cs, int baudrate);
void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self);
void common_hal_sdcardio_sdcard_check_for_deinit(sdcardio_sdcard_obj_t *self);
int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self);
int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf);
int common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self);
int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf);
// Used by native vfs blockdev.
mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t buflen);
mp_uint_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t buflen);
bool sdcardio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value);

View file

@ -164,7 +164,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(sdioio_sdcard_count_obj, sdioio_sdcard_count);
//| :param ~circuitpython_typing.WriteableBuffer buf: The buffer to write into. Length must be multiple of 512. //| :param ~circuitpython_typing.WriteableBuffer buf: The buffer to write into. Length must be multiple of 512.
//| //|
//| :return: None""" //| :return: None"""
STATIC mp_obj_t sdioio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) { STATIC mp_obj_t _sdioio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
uint32_t start_block = mp_obj_get_int(start_block_in); uint32_t start_block = mp_obj_get_int(start_block_in);
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
@ -176,7 +176,7 @@ STATIC mp_obj_t sdioio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_
return mp_const_none; return mp_const_none;
} }
MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_readblocks_obj, sdioio_sdcard_readblocks); MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_readblocks_obj, _sdioio_sdcard_readblocks);
//| def writeblocks(self, start_block: int, buf: ReadableBuffer) -> None: //| def writeblocks(self, start_block: int, buf: ReadableBuffer) -> None:
//| """Write one or more blocks to the card //| """Write one or more blocks to the card
@ -185,7 +185,7 @@ MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_readblocks_obj, sdioio_sdcard_readblocks
//| :param ~circuitpython_typing.ReadableBuffer buf: The buffer to read from. Length must be multiple of 512. //| :param ~circuitpython_typing.ReadableBuffer buf: The buffer to read from. Length must be multiple of 512.
//| //|
//| :return: None""" //| :return: None"""
STATIC mp_obj_t sdioio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) { STATIC mp_obj_t _sdioio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
uint32_t start_block = mp_obj_get_int(start_block_in); uint32_t start_block = mp_obj_get_int(start_block_in);
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
@ -197,7 +197,7 @@ STATIC mp_obj_t sdioio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block
return mp_const_none; return mp_const_none;
} }
MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_writeblocks_obj, sdioio_sdcard_writeblocks); MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_writeblocks_obj, _sdioio_sdcard_writeblocks);
//| frequency: int //| frequency: int
//| """The actual SDIO bus frequency. This may not match the frequency //| """The actual SDIO bus frequency. This may not match the frequency

View file

@ -130,11 +130,12 @@ STATIC mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos
mp_arg_val_t sticky_on_reload; mp_arg_val_t sticky_on_reload;
} args; } args;
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t *)&args); mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t *)&args);
if (!mp_obj_is_str_or_bytes(args.filename.u_obj) && args.filename.u_obj != mp_const_none) { mp_obj_t filename_obj = args.filename.u_obj;
mp_raise_TypeError(MP_ERROR_TEXT("argument has wrong type")); if (!mp_obj_is_str_or_bytes(filename_obj) && filename_obj != mp_const_none) {
mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q or %q, not %q"), MP_QSTR_filename, MP_QSTR_str, MP_QSTR_None, mp_obj_get_type(filename_obj)->name);
} }
if (args.filename.u_obj == mp_const_none) { if (filename_obj == mp_const_none) {
args.filename.u_obj = mp_const_empty_bytes; filename_obj = mp_const_empty_bytes;
} }
uint8_t options = 0; uint8_t options = 0;
if (args.reload_on_success.u_bool) { if (args.reload_on_success.u_bool) {
@ -153,7 +154,7 @@ STATIC mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos
options |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_RELOAD; options |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_RELOAD;
} }
size_t len; size_t len;
const char *filename = mp_obj_str_get_data(args.filename.u_obj, &len); const char *filename = mp_obj_str_get_data(filename_obj, &len);
if (next_code_configuration != NULL) { if (next_code_configuration != NULL) {
port_free(next_code_configuration); port_free(next_code_configuration);
next_code_configuration = NULL; next_code_configuration = NULL;

View file

@ -83,9 +83,7 @@ STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
mp_int_t seconds = mp_obj_get_int(seconds_o); mp_int_t seconds = mp_obj_get_int(seconds_o);
mp_int_t msecs = 1000 * seconds; mp_int_t msecs = 1000 * seconds;
#endif #endif
if (seconds < 0) { mp_arg_validate_int_min(msecs, 0, MP_QSTR_seconds);
mp_raise_ValueError(MP_ERROR_TEXT("sleep length must be non-negative"));
}
common_hal_time_delay_ms(msecs); common_hal_time_delay_ms(msecs);
return mp_const_none; return mp_const_none;
} }
@ -161,13 +159,13 @@ void struct_time_to_tm(mp_obj_t t, timeutils_struct_time_t *tm) {
mp_obj_t *elems; mp_obj_t *elems;
size_t len; size_t len;
if (!mp_obj_is_type(t, &mp_type_tuple) && !mp_obj_is_type(t, (mp_obj_type_t *)&struct_time_type_obj.base)) { if (!mp_obj_is_type(t, &mp_type_tuple)) {
mp_raise_TypeError(MP_ERROR_TEXT("Tuple or struct_time argument required")); mp_arg_validate_type(t, (mp_obj_type_t *)&struct_time_type_obj.base, MP_QSTR_value);
} }
mp_obj_tuple_get(t, &len, &elems); mp_obj_tuple_get(t, &len, &elems);
if (len != 9) { if (len != 9) {
mp_raise_TypeError(MP_ERROR_TEXT("function takes exactly 9 arguments")); mp_raise_TypeError_varg(MP_ERROR_TEXT("function takes %d positional arguments but %d were given"), 9, len);
} }
tm->tm_year = mp_obj_get_int(elems[0]); tm->tm_year = mp_obj_get_int(elems[0]);
@ -277,8 +275,8 @@ STATIC mp_obj_t time_mktime(mp_obj_t t) {
mp_obj_t *elem; mp_obj_t *elem;
size_t len; size_t len;
if (!mp_obj_is_type(t, &mp_type_tuple) && !mp_obj_is_type(t, (mp_obj_type_t *)&struct_time_type_obj.base)) { if (!mp_obj_is_type(t, &mp_type_tuple)) {
mp_raise_TypeError(MP_ERROR_TEXT("Tuple or struct_time argument required")); mp_arg_validate_type(t, (mp_obj_type_t *)&struct_time_type_obj.base, MP_QSTR_value);
} }
mp_obj_tuple_get(t, &len, &elem); mp_obj_tuple_get(t, &len, &elem);
@ -287,7 +285,7 @@ STATIC mp_obj_t time_mktime(mp_obj_t t) {
} }
if (mp_obj_get_int(elem[0]) < 2000) { if (mp_obj_get_int(elem[0]) < 2000) {
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("timestamp out of range for platform time_t")); mp_raise_msg_varg(&mp_type_OverflowError, MP_ERROR_TEXT("%q out of range"), MP_QSTR_tm_year);
} }
mp_uint_t secs = timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_uint_t secs = timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]),

View file

@ -72,6 +72,9 @@
//| in_report_lengths=(5, 2), //| in_report_lengths=(5, 2),
//| out_report_lengths=(6, 0), //| out_report_lengths=(6, 0),
//| ) //| )
//|
//| The HID device is able to wake up a suspended (sleeping) host computer.
//| See `send_report()` for details.
//| """ //| """
//| ... //| ...
//| KEYBOARD: Device //| KEYBOARD: Device
@ -166,6 +169,16 @@ STATIC mp_obj_t usb_hid_device_make_new(const mp_obj_type_t *type, size_t n_args
//| """Send an HID report. If the device descriptor specifies zero or one report id's, //| """Send an HID report. If the device descriptor specifies zero or one report id's,
//| you can supply `None` (the default) as the value of ``report_id``. //| you can supply `None` (the default) as the value of ``report_id``.
//| Otherwise you must specify which report id to use when sending the report. //| Otherwise you must specify which report id to use when sending the report.
//|
//| If the USB host is suspended (sleeping), then `send_report()` will request that the host wake up.
//| The ``report`` itself will be discarded, to prevent unwanted extraneous characters,
//| mouse clicks, etc.
//|
//| Note: Host operating systems allow enabling and disabling specific devices
//| and kinds of devices to do wakeup.
//| The defaults are different for different operating systems.
//| For instance, on Linux, only the primary keyboard may be enabled.
//| In addition, there may be USB wakeup settings in the host computer BIOS/UEFI.
//| """ //| """
//| ... //| ...
STATIC mp_obj_t usb_hid_device_send_report(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC mp_obj_t usb_hid_device_send_report(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {

View file

@ -31,7 +31,7 @@
#pragma GCC diagnostic ignored "-Wshadow" #pragma GCC diagnostic ignored "-Wshadow"
static void check_matching_details(displayio_bitmap_t *b1, displayio_bitmap_t *b2) { static void check_matching_details(displayio_bitmap_t *b1, displayio_bitmap_t *b2) {
if (b1->width != b2->width || b1->height != b2->height) { if (b1->width != b2->width || b1->height != b2->height || b1->bits_per_value != b2->bits_per_value) {
mp_raise_ValueError(MP_ERROR_TEXT("bitmap size and depth must match")); mp_raise_ValueError(MP_ERROR_TEXT("bitmap size and depth must match"));
} }
} }
@ -105,8 +105,6 @@ void shared_module_bitmapfilter_morph(
const int32_t m_int = (int32_t)MICROPY_FLOAT_C_FUN(round)(65536 * m); const int32_t m_int = (int32_t)MICROPY_FLOAT_C_FUN(round)(65536 * m);
const int32_t b_int = (int32_t)MICROPY_FLOAT_C_FUN(round)(65536 * COLOR_G6_MAX * b); const int32_t b_int = (int32_t)MICROPY_FLOAT_C_FUN(round)(65536 * COLOR_G6_MAX * b);
check_matching_details(bitmap, bitmap);
switch (bitmap->bits_per_value) { switch (bitmap->bits_per_value) {
default: default:
mp_raise_ValueError(MP_ERROR_TEXT("unsupported bitmap depth")); mp_raise_ValueError(MP_ERROR_TEXT("unsupported bitmap depth"));
@ -220,8 +218,6 @@ void shared_module_bitmapfilter_mix(
wt[i] = (int32_t)MICROPY_FLOAT_C_FUN(round)(scale * weights[i]); wt[i] = (int32_t)MICROPY_FLOAT_C_FUN(round)(scale * weights[i]);
} }
check_matching_details(bitmap, bitmap);
switch (bitmap->bits_per_value) { switch (bitmap->bits_per_value) {
default: default:
mp_raise_ValueError(MP_ERROR_TEXT("unsupported bitmap depth")); mp_raise_ValueError(MP_ERROR_TEXT("unsupported bitmap depth"));
@ -368,3 +364,64 @@ void shared_module_bitmapfilter_false_color(
} }
} }
} }
void shared_module_bitmapfilter_blend_precompute(mp_obj_t fun, uint8_t lookup[4096]) {
uint8_t *ptr = lookup;
for (int i = 0; i < 64; i++) {
mp_obj_t fi = mp_obj_new_float(i * (1 / MICROPY_FLOAT_CONST(63.)));
for (int j = 0; j < 64; j++) {
mp_obj_t fj = mp_obj_new_float(j * (1 / MICROPY_FLOAT_CONST(63.)));
mp_float_t res = mp_obj_get_float(mp_call_function_2(fun, fi, fj));
*ptr++ = res < 0 ? 0 : res > 1 ? 1 : (uint8_t)MICROPY_FLOAT_C_FUN(round)(63 * res);
}
}
}
#define FIVE_TO_SIX(x) ({ int tmp = (x); (tmp << 1) | (tmp & 1); })
#define SIX_TO_FIVE(x) ((x) >> 1)
void shared_module_bitmapfilter_blend(
displayio_bitmap_t *bitmap,
displayio_bitmap_t *src1,
displayio_bitmap_t *src2,
displayio_bitmap_t *mask,
const uint8_t lookup[4096]) {
check_matching_details(bitmap, src1);
check_matching_details(bitmap, src2);
switch (bitmap->bits_per_value) {
default:
mp_raise_ValueError(MP_ERROR_TEXT("unsupported bitmap depth"));
case 16: {
for (int y = 0, yy = bitmap->height; y < yy; y++) {
uint16_t *dest_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(bitmap, y);
uint16_t *src1_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(src1, y);
uint16_t *src2_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(src2, y);
for (int x = 0, xx = bitmap->width; x < xx; x++) {
int pixel1 = IMAGE_GET_RGB565_PIXEL_FAST(src1_ptr, x);
if (mask && common_hal_displayio_bitmap_get_pixel(mask, x, y)) {
IMAGE_PUT_RGB565_PIXEL_FAST(dest_ptr, x, pixel1);
continue; // Short circuit.
}
int pixel2 = IMAGE_GET_RGB565_PIXEL_FAST(src2_ptr, x);
int r1 = FIVE_TO_SIX(COLOR_RGB565_TO_R5(pixel1));
int r2 = FIVE_TO_SIX(COLOR_RGB565_TO_R5(pixel2));
int r = SIX_TO_FIVE(lookup[r1 * 64 + r2]);
int g1 = COLOR_RGB565_TO_G6(pixel1);
int g2 = COLOR_RGB565_TO_G6(pixel2);
int g = lookup[g1 * 64 + g2];
int b1 = FIVE_TO_SIX(COLOR_RGB565_TO_B5(pixel1));
int b2 = FIVE_TO_SIX(COLOR_RGB565_TO_B5(pixel2));
int b = SIX_TO_FIVE(lookup[b1 * 64 + b2]);
int pixel = COLOR_R5_G6_B5_TO_RGB565(r, g, b);
IMAGE_PUT_RGB565_PIXEL_FAST(dest_ptr, x, pixel);
}
}
}
}
}

View file

@ -507,6 +507,7 @@ void epaperdisplay_epaperdisplay_collect_ptrs(epaperdisplay_epaperdisplay_obj_t
displayio_display_bus_collect_ptrs(&self->bus); displayio_display_bus_collect_ptrs(&self->bus);
gc_collect_ptr((void *)self->start_sequence); gc_collect_ptr((void *)self->start_sequence);
gc_collect_ptr((void *)self->stop_sequence); gc_collect_ptr((void *)self->stop_sequence);
gc_collect_ptr((void *)self->refresh_sequence);
} }
size_t maybe_refresh_epaperdisplay(void) { size_t maybe_refresh_epaperdisplay(void) {

View file

@ -62,8 +62,12 @@ STATIC bool open_file(const char *name, file_arg *active_file) {
return false; return false;
} }
#else #else
FATFS *fs = filesystem_circuitpy(); fs_user_mount_t *fs_mount = filesystem_circuitpy();
FRESULT result = f_open(fs, active_file, name, FA_READ); if (fs_mount == NULL) {
return false;
}
FATFS *fatfs = &fs_mount->fatfs;
FRESULT result = f_open(fatfs, active_file, name, FA_READ);
return result == FR_OK; return result == FR_OK;
#endif #endif
} }

View file

@ -26,6 +26,8 @@
// This implementation largely follows the structure of adafruit_sdcard.py // This implementation largely follows the structure of adafruit_sdcard.py
#include "extmod/vfs.h"
#include "shared-bindings/busio/SPI.h" #include "shared-bindings/busio/SPI.h"
#include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/sdcardio/SDCard.h" #include "shared-bindings/sdcardio/SDCard.h"
@ -358,23 +360,24 @@ STATIC int readinto(sdcardio_sdcard_obj_t *self, void *buf, size_t size) {
return 0; return 0;
} }
STATIC int readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t nblocks) {
uint32_t nblocks = buf->len / 512; sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (!lock_and_configure_bus(self)) {
return MP_EAGAIN;
}
int r = 0;
size_t buflen = 512 * nblocks;
if (nblocks == 1) { if (nblocks == 1) {
// Use CMD17 to read a single block // Use CMD17 to read a single block
return block_cmd(self, 17, start_block, buf->buf, buf->len, true, true); r = block_cmd(self, 17, start_block, buf, buflen, true, true);
} else { } else {
// Use CMD18 to read multiple blocks // Use CMD18 to read multiple blocks
int r = block_cmd(self, 18, start_block, NULL, 0, true, true); r = block_cmd(self, 18, start_block, NULL, 0, true, true);
if (r < 0) { uint8_t *ptr = buf;
return r; while (nblocks-- && r >= 0) {
}
uint8_t *ptr = buf->buf;
while (nblocks--) {
r = readinto(self, ptr, 512); r = readinto(self, ptr, 512);
if (r < 0) { if (r != 0) {
return r; break;
} }
ptr += 512; ptr += 512;
} }
@ -387,12 +390,13 @@ STATIC int readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buff
uint8_t single_byte; uint8_t single_byte;
common_hal_busio_spi_read(self->bus, &single_byte, 1, 0xff); common_hal_busio_spi_read(self->bus, &single_byte, 1, 0xff);
if (single_byte & 0x80) { if (single_byte & 0x80) {
return r; break;
} }
r = single_byte; r = single_byte;
} }
} }
return 0; extraclock_and_unlock_bus(self);
return r;
} }
int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) {
@ -401,10 +405,7 @@ int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t
mp_raise_ValueError(MP_ERROR_TEXT("Buffer length must be a multiple of 512")); mp_raise_ValueError(MP_ERROR_TEXT("Buffer length must be a multiple of 512"));
} }
lock_and_configure_bus(self); return sdcardio_sdcard_readblocks(MP_OBJ_FROM_PTR(self), buf->buf, start_block, buf->len / 512);
int r = readblocks(self, start_block, buf);
extraclock_and_unlock_bus(self);
return r;
} }
STATIC int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t size) { STATIC int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t size) {
@ -452,17 +453,20 @@ STATIC int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t
return 0; return 0;
} }
STATIC int writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { mp_uint_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t nblocks) {
sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_sdcardio_check_for_deinit(self); common_hal_sdcardio_check_for_deinit(self);
uint32_t nblocks = buf->len / 512;
DEBUG_PRINT("cmd25? %d next_block %d start_block %d\n", self->in_cmd25, self->next_block, start_block); if (!lock_and_configure_bus(self)) {
return MP_EAGAIN;
}
if (!self->in_cmd25 || start_block != self->next_block) { if (!self->in_cmd25 || start_block != self->next_block) {
DEBUG_PRINT("entering CMD25 at %d\n", (int)start_block); DEBUG_PRINT("entering CMD25 at %d\n", (int)start_block);
// Use CMD25 to write multiple block // Use CMD25 to write multiple block
int r = block_cmd(self, 25, start_block, NULL, 0, true, true); int r = block_cmd(self, 25, start_block, NULL, 0, true, true);
if (r < 0) { if (r < 0) {
extraclock_and_unlock_bus(self);
return r; return r;
} }
self->in_cmd25 = true; self->in_cmd25 = true;
@ -470,17 +474,19 @@ STATIC int writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buf
self->next_block = start_block; self->next_block = start_block;
uint8_t *ptr = buf->buf; uint8_t *ptr = buf;
while (nblocks--) { while (nblocks--) {
int r = _write(self, TOKEN_CMD25, ptr, 512); int r = _write(self, TOKEN_CMD25, ptr, 512);
if (r < 0) { if (r < 0) {
self->in_cmd25 = false; self->in_cmd25 = false;
extraclock_and_unlock_bus(self);
return r; return r;
} }
self->next_block++; self->next_block++;
ptr += 512; ptr += 512;
} }
extraclock_and_unlock_bus(self);
return 0; return 0;
} }
@ -498,7 +504,29 @@ int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t
mp_raise_ValueError(MP_ERROR_TEXT("Buffer length must be a multiple of 512")); mp_raise_ValueError(MP_ERROR_TEXT("Buffer length must be a multiple of 512"));
} }
lock_and_configure_bus(self); lock_and_configure_bus(self);
int r = writeblocks(self, start_block, buf); int r = sdcardio_sdcard_writeblocks(MP_OBJ_FROM_PTR(self), buf->buf, start_block, buf->len / 512);
extraclock_and_unlock_bus(self); extraclock_and_unlock_bus(self);
return r; return r;
} }
bool sdcardio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value) {
sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
*out_value = 0;
switch (cmd) {
case MP_BLOCKDEV_IOCTL_DEINIT:
common_hal_sdcardio_sdcard_sync(self);
break; // TODO properly
case MP_BLOCKDEV_IOCTL_SYNC:
common_hal_sdcardio_sdcard_sync(self);
break;
case MP_BLOCKDEV_IOCTL_BLOCK_COUNT:
*out_value = common_hal_sdcardio_sdcard_get_blockcount(self);
break;
case MP_BLOCKDEV_IOCTL_BLOCK_SIZE:
*out_value = 512;
break;
default:
return false;
}
return true;
}

View file

@ -44,11 +44,3 @@ typedef struct {
uint32_t next_block; uint32_t next_block;
bool in_cmd25; bool in_cmd25;
} sdcardio_sdcard_obj_t; } sdcardio_sdcard_obj_t;
void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *spi, const mcu_pin_obj_t *cs, int baudrate);
void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self);
void common_hal_sdcardio_sdcard_check_for_deinit(sdcardio_sdcard_obj_t *self);
int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self);
int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf);
int common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self);
int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf);

View file

@ -177,15 +177,20 @@ void common_hal_storage_mount(mp_obj_t vfs_obj, const char *mount_path, bool rea
args[0] = readonly ? mp_const_true : mp_const_false; args[0] = readonly ? mp_const_true : mp_const_false;
args[1] = mp_const_false; // Don't make the file system automatically when mounting. args[1] = mp_const_false; // Don't make the file system automatically when mounting.
// Check that there's no file or directory with the same name as the mount point. // Check that there is a directory with the same name as the mount point.
// But it's ok to mount '/' in any case. // But it's ok to mount '/' in any case.
if (strcmp(vfs->str, "/") != 0) { if (strcmp(vfs->str, "/") != 0) {
nlr_buf_t nlr; nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) { if (nlr_push(&nlr) == 0) {
common_hal_os_stat(mount_path); mp_obj_t mount_point_stat = common_hal_os_stat(mount_path);
nlr_pop(); nlr_pop();
// Something with the same name exists. mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mount_point_stat);
mp_raise_OSError(MP_EEXIST); if ((MP_OBJ_SMALL_INT_VALUE(t->items[0]) & MP_S_IFDIR) == 0) {
mp_raise_RuntimeError(MP_ERROR_TEXT("Mount point directory missing"));
}
} else {
// Something with the same name doesn't exist.
mp_raise_RuntimeError(MP_ERROR_TEXT("Mount point directory missing"));
} }
} }

View file

@ -229,6 +229,7 @@ void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t *
RUN_BACKGROUND_TASKS; RUN_BACKGROUND_TASKS;
} }
if (!tud_suspended()) {
if (!tud_hid_ready()) { if (!tud_hid_ready()) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("USB busy")); mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("USB busy"));
} }
@ -236,6 +237,9 @@ void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t *
if (!tud_hid_report(report_id, report, len)) { if (!tud_hid_report(report_id, report, len)) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("USB error")); mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("USB error"));
} }
} else {
tud_remote_wakeup();
}
} }
mp_obj_t common_hal_usb_hid_device_get_last_received_report(usb_hid_device_obj_t *self, uint8_t report_id) { mp_obj_t common_hal_usb_hid_device_get_last_received_report(usb_hid_device_obj_t *self, uint8_t report_id) {

View file

@ -602,7 +602,7 @@ raw_repl_reset:
} }
int ret = parse_compile_execute(&line, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR, NULL); int ret = parse_compile_execute(&line, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR, NULL);
if (ret & PYEXEC_FORCED_EXIT) { if (ret & (PYEXEC_FORCED_EXIT | PYEXEC_RELOAD)) {
return ret; return ret;
} }
} }
@ -739,7 +739,7 @@ friendly_repl_reset:
} }
ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR, NULL); ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR, NULL);
if (ret & PYEXEC_FORCED_EXIT) { if (ret & (PYEXEC_FORCED_EXIT | PYEXEC_RELOAD)) {
return ret; return ret;
} }
} }

View file

@ -24,8 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_SUPERVISOR_FILESYSTEM_H #pragma once
#define MICROPY_INCLUDED_SUPERVISOR_FILESYSTEM_H
#include <stdbool.h> #include <stdbool.h>
@ -45,6 +44,16 @@ void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concu
bool filesystem_is_writable_by_python(fs_user_mount_t *vfs); bool filesystem_is_writable_by_python(fs_user_mount_t *vfs);
bool filesystem_is_writable_by_usb(fs_user_mount_t *vfs); bool filesystem_is_writable_by_usb(fs_user_mount_t *vfs);
FATFS *filesystem_circuitpy(void); fs_user_mount_t *filesystem_circuitpy(void);
fs_user_mount_t *filesystem_for_path(const char *path_in, const char **path_under_mount);
bool filesystem_native_fatfs(fs_user_mount_t *fs_mount);
#endif // MICROPY_INCLUDED_SUPERVISOR_FILESYSTEM_H // We have two levels of locking. filesystem_* calls grab a shared blockdev lock to allow
// CircuitPython's fatfs code edit the blocks. blockdev_* class grab a lock to mutate blocks
// directly, excluding any filesystem_* locks.
bool filesystem_lock(fs_user_mount_t *fs_mount);
void filesystem_unlock(fs_user_mount_t *fs_mount);
bool blockdev_lock(fs_user_mount_t *fs_mount);
void blockdev_unlock(fs_user_mount_t *fs_mount);

View file

@ -126,13 +126,21 @@ void background_callback_reset() {
background_callback_t *cb = (background_callback_t *)callback_head; background_callback_t *cb = (background_callback_t *)callback_head;
while (cb) { while (cb) {
background_callback_t *next = cb->next; background_callback_t *next = cb->next;
if (gc_ptr_on_heap((void *)cb)) {
*previous_next = cb;
previous_next = &cb->next;
cb->next = NULL; cb->next = NULL;
new_tail = cb; // Unlink any callbacks that are allocated on the python heap or if they
// reference data on the python heap. The python heap will be disappear
// soon after this.
if (gc_ptr_on_heap((void *)cb) || gc_ptr_on_heap(cb->data)) {
cb->prev = NULL; // Used to indicate a callback isn't queued.
} else { } else {
memset(cb, 0, sizeof(*cb)); // Set .next of the previous callback.
*previous_next = cb;
// Set our .next for the next callback.
previous_next = &cb->next;
// Set our prev to the last callback.
cb->prev = new_tail;
// Now we're the tail of the list.
new_tail = cb;
} }
cb = next; cb = next;
} }

View file

@ -151,6 +151,7 @@ STATIC uint64_t truncate_time(uint64_t input_time, DWORD *fattime) {
// Used by read and write. // Used by read and write.
STATIC FIL active_file; STATIC FIL active_file;
STATIC fs_user_mount_t *active_mount;
STATIC uint8_t _process_read(const uint8_t *raw_buf, size_t command_len) { STATIC uint8_t _process_read(const uint8_t *raw_buf, size_t command_len) {
struct read_command *command = (struct read_command *)raw_buf; struct read_command *command = (struct read_command *)raw_buf;
size_t header_size = sizeof(struct read_command); size_t header_size = sizeof(struct read_command);
@ -170,11 +171,19 @@ STATIC uint8_t _process_read(const uint8_t *raw_buf, size_t command_len) {
return THIS_COMMAND; return THIS_COMMAND;
} }
char *path = (char *)((uint8_t *)command) + header_size; char *full_path = (char *)((uint8_t *)command) + header_size;
path[command->path_length] = '\0'; full_path[command->path_length] = '\0';
FATFS *fs = filesystem_circuitpy(); const char *mount_path;
FRESULT result = f_open(fs, &active_file, path, FA_READ); active_mount = filesystem_for_path(full_path, &mount_path);
if (active_mount == NULL || !filesystem_native_fatfs(active_mount)) {
response.status = STATUS_ERROR;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, response_size, NULL, 0);
return ANY_COMMAND;
}
FATFS *fs = &active_mount->fatfs;
FRESULT result = f_open(fs, &active_file, mount_path, FA_READ);
if (result != FR_OK) { if (result != FR_OK) {
response.status = STATUS_ERROR; response.status = STATUS_ERROR;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, response_size, NULL, 0); common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, response_size, NULL, 0);
@ -250,22 +259,6 @@ STATIC uint8_t _process_read_pacing(const uint8_t *raw_buf, size_t command_len)
STATIC size_t total_write_length; STATIC size_t total_write_length;
STATIC uint64_t _truncated_time; STATIC uint64_t _truncated_time;
// Returns true if usb is active and replies with an error if so. If not, it grabs
// the USB mass storage lock and returns false. Make sure to release the lock with
// usb_msc_unlock() when the transaction is complete.
STATIC bool _usb_active(void *response, size_t response_size) {
// Check to see if USB has already been mounted. If not, then we "eject" from USB until we're done.
#if CIRCUITPY_USB && CIRCUITPY_USB_MSC
if (storage_usb_enabled() && !usb_msc_lock()) {
// Status is always the second byte of the response.
((uint8_t *)response)[1] = STATUS_ERROR_READONLY;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)response, response_size, NULL, 0);
return true;
}
#endif
return false;
}
STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) { STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) {
struct write_command *command = (struct write_command *)raw_buf; struct write_command *command = (struct write_command *)raw_buf;
size_t header_size = sizeof(struct write_command); size_t header_size = sizeof(struct write_command);
@ -284,23 +277,31 @@ STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) {
} }
total_write_length = command->total_length; total_write_length = command->total_length;
char *path = (char *)command->path; char *full_path = (char *)command->path;
path[command->path_length] = '\0'; full_path[command->path_length] = '\0';
if (_usb_active(&response, sizeof(struct write_pacing))) {
const char *mount_path;
active_mount = filesystem_for_path(full_path, &mount_path);
if (active_mount == NULL || !filesystem_native_fatfs(active_mount)) {
response.status = STATUS_ERROR;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0);
return ANY_COMMAND;
}
if (!filesystem_lock(active_mount)) {
response.status = STATUS_ERROR_READONLY;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0);
return ANY_COMMAND; return ANY_COMMAND;
} }
FATFS *fs = filesystem_circuitpy(); FATFS *fs = &active_mount->fatfs;
DWORD fattime; DWORD fattime;
_truncated_time = truncate_time(command->modification_time, &fattime); _truncated_time = truncate_time(command->modification_time, &fattime);
override_fattime(fattime); override_fattime(fattime);
FRESULT result = f_open(fs, &active_file, path, FA_WRITE | FA_OPEN_ALWAYS); FRESULT result = f_open(fs, &active_file, mount_path, FA_WRITE | FA_OPEN_ALWAYS);
if (result != FR_OK) { if (result != FR_OK) {
response.status = STATUS_ERROR; response.status = STATUS_ERROR;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0); common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0);
#if CIRCUITPY_USB_MSC filesystem_unlock(active_mount);
usb_msc_unlock();
#endif
override_fattime(0); override_fattime(0);
return ANY_COMMAND; return ANY_COMMAND;
} }
@ -315,9 +316,7 @@ STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) {
f_truncate(&active_file); f_truncate(&active_file);
f_close(&active_file); f_close(&active_file);
override_fattime(0); override_fattime(0);
#if CIRCUITPY_USB_MSC filesystem_unlock(active_mount);
usb_msc_unlock();
#endif
} }
response.offset = offset; response.offset = offset;
response.free_space = chunk_size; response.free_space = chunk_size;
@ -342,9 +341,7 @@ STATIC uint8_t _process_write_data(const uint8_t *raw_buf, size_t command_len) {
// TODO: throw away any more packets of path. // TODO: throw away any more packets of path.
response.status = STATUS_ERROR; response.status = STATUS_ERROR;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0); common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0);
#if CIRCUITPY_USB_MSC filesystem_unlock(active_mount);
usb_msc_unlock();
#endif
override_fattime(0); override_fattime(0);
return ANY_COMMAND; return ANY_COMMAND;
} }
@ -360,9 +357,7 @@ STATIC uint8_t _process_write_data(const uint8_t *raw_buf, size_t command_len) {
// TODO: throw away any more packets of path. // TODO: throw away any more packets of path.
response.status = STATUS_ERROR; response.status = STATUS_ERROR;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0); common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0);
#if CIRCUITPY_USB_MSC filesystem_unlock(active_mount);
usb_msc_unlock();
#endif
override_fattime(0); override_fattime(0);
return ANY_COMMAND; return ANY_COMMAND;
} }
@ -377,9 +372,7 @@ STATIC uint8_t _process_write_data(const uint8_t *raw_buf, size_t command_len) {
f_truncate(&active_file); f_truncate(&active_file);
f_close(&active_file); f_close(&active_file);
override_fattime(0); override_fattime(0);
#if CIRCUITPY_USB_MSC filesystem_unlock(active_mount);
usb_msc_unlock();
#endif
// Don't reload until everything is written out of the packet buffer. // Don't reload until everything is written out of the packet buffer.
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer); common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
return ANY_COMMAND; return ANY_COMMAND;
@ -399,29 +392,19 @@ STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) {
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct delete_status), NULL, 0); common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct delete_status), NULL, 0);
return ANY_COMMAND; return ANY_COMMAND;
} }
if (_usb_active(&response, sizeof(struct delete_status))) {
return ANY_COMMAND;
}
// We need to receive another packet to have the full path. // We need to receive another packet to have the full path.
if (command_len < header_size + command->path_length) { if (command_len < header_size + command->path_length) {
return THIS_COMMAND; return THIS_COMMAND;
} }
FATFS *fs = filesystem_circuitpy();
char *path = (char *)((uint8_t *)command) + header_size; char *full_path = (char *)((uint8_t *)command) + header_size;
path[command->path_length] = '\0'; full_path[command->path_length] = '\0';
FILINFO file;
FRESULT result = f_stat(fs, path, &file); FRESULT result = supervisor_workflow_delete_recursive(full_path);
if (result == FR_OK) {
if ((file.fattrib & AM_DIR) != 0) { if (result == FR_WRITE_PROTECTED) {
result = supervisor_workflow_delete_directory_contents(fs, path); response.status = STATUS_ERROR_READONLY;
} }
if (result == FR_OK) {
result = f_unlink(fs, path);
}
}
#if CIRCUITPY_USB_MSC
usb_msc_unlock();
#endif
if (result != FR_OK) { if (result != FR_OK) {
response.status = STATUS_ERROR; response.status = STATUS_ERROR;
} }
@ -456,25 +439,16 @@ STATIC uint8_t _process_mkdir(const uint8_t *raw_buf, size_t command_len) {
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct mkdir_status), NULL, 0); common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct mkdir_status), NULL, 0);
return ANY_COMMAND; return ANY_COMMAND;
} }
if (_usb_active(&response, sizeof(struct mkdir_status))) {
return ANY_COMMAND;
}
// We need to receive another packet to have the full path. // We need to receive another packet to have the full path.
if (command_len < header_size + command->path_length) { if (command_len < header_size + command->path_length) {
return THIS_COMMAND; return THIS_COMMAND;
} }
FATFS *fs = filesystem_circuitpy(); char *full_path = (char *)command->path;
char *path = (char *)command->path; _terminate_path(full_path, command->path_length);
_terminate_path(path, command->path_length);
DWORD fattime; DWORD fattime;
response.truncated_time = truncate_time(command->modification_time, &fattime); response.truncated_time = truncate_time(command->modification_time, &fattime);
override_fattime(fattime); FRESULT result = supervisor_workflow_mkdir(fattime, full_path);
FRESULT result = supervisor_workflow_mkdir_parents(fs, path);
override_fattime(0);
#if CIRCUITPY_USB_MSC
usb_msc_unlock();
#endif
if (result != FR_OK) { if (result != FR_OK) {
response.status = STATUS_ERROR; response.status = STATUS_ERROR;
} }
@ -520,12 +494,21 @@ STATIC uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) {
return THIS_COMMAND; return THIS_COMMAND;
} }
FATFS *fs = filesystem_circuitpy(); char *full_path = (char *)&command->path;
char *path = (char *)&command->path; _terminate_path(full_path, command->path_length);
_terminate_path(path, command->path_length);
// mp_printf(&mp_plat_print, "list %s\n", path); const char *mount_path;
active_mount = filesystem_for_path(full_path, &mount_path);
if (active_mount == NULL || !filesystem_native_fatfs(active_mount)) {
entry->command = LISTDIR_ENTRY;
entry->status = STATUS_ERROR_NO_FILE;
send_listdir_entry_header(entry, max_packet_size);
return ANY_COMMAND;
}
FATFS *fs = &active_mount->fatfs;
FF_DIR dir; FF_DIR dir;
FRESULT res = f_opendir(fs, &dir, path); FRESULT res = f_opendir(fs, &dir, mount_path);
entry->command = LISTDIR_ENTRY; entry->command = LISTDIR_ENTRY;
entry->status = STATUS_OK; entry->status = STATUS_OK;
@ -601,27 +584,21 @@ STATIC uint8_t _process_move(const uint8_t *raw_buf, size_t command_len) {
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct move_status), NULL, 0); common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct move_status), NULL, 0);
return ANY_COMMAND; return ANY_COMMAND;
} }
if (_usb_active(&response, sizeof(struct move_status))) {
return ANY_COMMAND;
}
// We need to receive another packet to have the full path. // We need to receive another packet to have the full path.
if (command_len < header_size + total_path_length) { if (command_len < header_size + total_path_length) {
return THIS_COMMAND; return THIS_COMMAND;
} }
FATFS *fs = filesystem_circuitpy();
char *old_path = (char *)command->paths; char *old_path = (char *)command->paths;
old_path[command->old_path_length] = '\0'; old_path[command->old_path_length] = '\0';
char *new_path = old_path + command->old_path_length + 1; char *new_path = old_path + command->old_path_length + 1;
new_path[command->new_path_length] = '\0'; new_path[command->new_path_length] = '\0';
// mp_printf(&mp_plat_print, "move %s to %s\n", old_path, new_path); FRESULT result = supervisor_workflow_move(old_path, new_path);
if (result == FR_WRITE_PROTECTED) {
FRESULT result = f_rename(fs, old_path, new_path); response.status = STATUS_ERROR_READONLY;
#if CIRCUITPY_USB_MSC } else if (result != FR_OK) {
usb_msc_unlock();
#endif
if (result != FR_OK) {
response.status = STATUS_ERROR; response.status = STATUS_ERROR;
} }
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct move_status), NULL, 0); common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct move_status), NULL, 0);

View file

@ -221,9 +221,56 @@ bool filesystem_present(void) {
return _mp_vfs.len > 0; return _mp_vfs.len > 0;
} }
FATFS *filesystem_circuitpy(void) { fs_user_mount_t *filesystem_circuitpy(void) {
if (!filesystem_present()) { if (!filesystem_present()) {
return NULL; return NULL;
} }
return &_internal_vfs.fatfs; return &_internal_vfs;
}
fs_user_mount_t *filesystem_for_path(const char *path_in, const char **path_under_mount) {
mp_vfs_mount_t *vfs = mp_vfs_lookup_path(path_in, path_under_mount);
if (vfs == MP_VFS_NONE) {
return NULL;
}
fs_user_mount_t *fs_mount;
*path_under_mount = path_in;
if (vfs == MP_VFS_ROOT) {
fs_mount = filesystem_circuitpy();
} else {
fs_mount = MP_OBJ_TO_PTR(vfs->obj);
*path_under_mount += strlen(vfs->str);
}
return fs_mount;
}
bool filesystem_native_fatfs(fs_user_mount_t *fs_mount) {
return fs_mount->base.type == &mp_fat_vfs_type && (fs_mount->blockdev.flags & MP_BLOCKDEV_FLAG_NATIVE) != 0;
}
bool filesystem_lock(fs_user_mount_t *fs_mount) {
if (fs_mount->lock_count == 0 && !blockdev_lock(fs_mount)) {
return false;
}
fs_mount->lock_count += 1;
return true;
}
void filesystem_unlock(fs_user_mount_t *fs_mount) {
fs_mount->lock_count -= 1;
if (fs_mount->lock_count == 0) {
blockdev_unlock(fs_mount);
}
}
bool blockdev_lock(fs_user_mount_t *fs_mount) {
if ((fs_mount->blockdev.flags & MP_BLOCKDEV_FLAG_LOCKED) != 0) {
return false;
}
fs_mount->blockdev.flags |= MP_BLOCKDEV_FLAG_LOCKED;
return true;
}
void blockdev_unlock(fs_user_mount_t *fs_mount) {
fs_mount->blockdev.flags &= ~MP_BLOCKDEV_FLAG_LOCKED;
} }

View file

@ -87,7 +87,7 @@ static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_blo
buf[15] = num_blocks >> 24; buf[15] = num_blocks >> 24;
} }
static mp_uint_t flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { static mp_uint_t flash_read_blocks(mp_obj_t self, uint8_t *dest, uint32_t block_num, uint32_t num_blocks) {
if (block_num == 0) { if (block_num == 0) {
// fake the MBR so we can decide on our own partition table // fake the MBR so we can decide on our own partition table
@ -117,7 +117,7 @@ static mp_uint_t flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t n
static volatile bool filesystem_dirty = false; static volatile bool filesystem_dirty = false;
static mp_uint_t flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { static mp_uint_t flash_write_blocks(mp_obj_t self, const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
if (block_num == 0) { if (block_num == 0) {
if (num_blocks > 1) { if (num_blocks > 1) {
return 1; // error return 1; // error
@ -150,7 +150,7 @@ void PLACE_IN_ITCM(supervisor_flash_flush)(void) {
STATIC mp_obj_t supervisor_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { STATIC mp_obj_t supervisor_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) {
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE);
mp_uint_t ret = flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); mp_uint_t ret = flash_read_blocks(self, bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE);
return MP_OBJ_NEW_SMALL_INT(ret); return MP_OBJ_NEW_SMALL_INT(ret);
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_readblocks_obj, supervisor_flash_obj_readblocks); STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_readblocks_obj, supervisor_flash_obj_readblocks);
@ -158,13 +158,15 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_readblocks_obj, supervisor
STATIC mp_obj_t supervisor_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { STATIC mp_obj_t supervisor_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) {
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
mp_uint_t ret = flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); mp_uint_t ret = flash_write_blocks(self, bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE);
return MP_OBJ_NEW_SMALL_INT(ret); return MP_OBJ_NEW_SMALL_INT(ret);
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_writeblocks_obj, supervisor_flash_obj_writeblocks); STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_writeblocks_obj, supervisor_flash_obj_writeblocks);
static bool flash_ioctl(size_t cmd, mp_int_t *out_value) { STATIC bool flash_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value) {
if (out_value != NULL) {
*out_value = 0; *out_value = 0;
}
switch (cmd) { switch (cmd) {
case MP_BLOCKDEV_IOCTL_INIT: case MP_BLOCKDEV_IOCTL_INIT:
supervisor_flash_init(); supervisor_flash_init();
@ -189,8 +191,9 @@ static bool flash_ioctl(size_t cmd, mp_int_t *out_value) {
STATIC mp_obj_t supervisor_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { STATIC mp_obj_t supervisor_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) {
mp_int_t cmd = mp_obj_get_int(cmd_in); mp_int_t cmd = mp_obj_get_int(cmd_in);
mp_int_t arg = mp_obj_get_int(arg_in);
mp_int_t out_value; mp_int_t out_value;
if (flash_ioctl(cmd, &out_value)) { if (flash_ioctl(self, cmd, arg, &out_value)) {
return MP_OBJ_NEW_SMALL_INT(out_value); return MP_OBJ_NEW_SMALL_INT(out_value);
} }
return mp_const_none; return mp_const_none;

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