1 Commits

Author SHA1 Message Date
9fdf5586f5 rp2/modmachine: Use atomic section macros.
To avoid undefined references to
mp_thread_begin_atomic_section/mp_thread_end_atomic_section, replace
them with the MICROPY_BEGIN_ATOMIC_SECTION / MICROPY_END_ATOMIC_SECTION
macros. That way, the support for building with MICROPY_PY_THREAD
disabled introduced by commit efa54c27b9 ("rp2/mpconfigport: Allow
MICROPY_PY_THREAD to be disabled by a board.") is useable again.

Fixes commit 19844b4983 ("rp2/modmachine: Prevent lock-up when
lightsleep() called within thread.").

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2024-05-31 19:00:13 +02:00
877 changed files with 5486 additions and 25108 deletions

View File

@@ -11,10 +11,19 @@ body:
* If you have a question \"How Do I ...?\", please post it on [GitHub Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead of here. * If you have a question \"How Do I ...?\", please post it on [GitHub Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead of here.
* For missing or incorrect documentation, or feature requests, then please [choose a different issue type](https://github.com/micropython/micropython/issues/new/choose). * For missing or incorrect documentation, or feature requests, then please [choose a different issue type](https://github.com/micropython/micropython/issues/new/choose).
- type: checkboxes
#### Existing issue? id: terms
attributes:
* Please search for [existing issues](https://github.com/micropython/micropython/issues) matching this bug before reporting. label: Checks
description: |
Before submitting your bug report, please go over these check points:
options:
- label: |
I agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone.
required: true
- label: |
I've searched for [existing issues](https://github.com/micropython/micropython/issues) matching this bug, and didn't find any.
required: true
- type: input - type: input
id: port-board-hw id: port-board-hw
attributes: attributes:
@@ -24,7 +33,7 @@ body:
placeholder: | placeholder: |
esp32 port, ESP32-Fantastic board. esp32 port, ESP32-Fantastic board.
validations: validations:
required: true required: true
- type: textarea - type: textarea
id: version id: version
attributes: attributes:
@@ -92,17 +101,6 @@ body:
description: | description: |
Is there anything else that might help to resolve this issue? Is there anything else that might help to resolve this issue?
value: No, I've provided everything above. value: No, I've provided everything above.
- type: dropdown
id: code-of-conduct
attributes:
label: Code of Conduct
description: |
Do you agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone?
options:
- "Yes, I agree"
multiple: true
validations:
required: true
- type: markdown - type: markdown
attributes: attributes:
value: | value: |

View File

@@ -9,10 +9,19 @@ body:
This form is for reporting issues with the documentation or examples provided with MicroPython. This form is for reporting issues with the documentation or examples provided with MicroPython.
If you have a general question \"How Do I ...?\", please post it on [GitHub Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead of here. If you have a general question \"How Do I ...?\", please post it on [GitHub Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead of here.
- type: checkboxes
#### Existing issue? id: terms
attributes:
* Please search for [existing issues](https://github.com/micropython/micropython/issues) before reporting a new one. label: Checks
description: |
Before submitting your bug report, please go over these check points:
options:
- label: |
I agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone.
required: true
- label: |
I've searched for [existing issues](https://github.com/micropython/micropython/issues) and didn't find any that matched.
required: true
- type: input - type: input
id: page id: page
attributes: attributes:
@@ -29,17 +38,6 @@ body:
Please describe what was missing from the documentation and/or what was incorrect/incomplete. Please describe what was missing from the documentation and/or what was incorrect/incomplete.
validations: validations:
required: true required: true
- type: dropdown
id: code-of-conduct
attributes:
label: Code of Conduct
description: |
Do you agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone?
options:
- "Yes, I agree"
multiple: true
validations:
required: true
- type: markdown - type: markdown
attributes: attributes:
value: | value: |

View File

@@ -15,10 +15,19 @@ body:
* If you have a question \"How Do I ...?\", please post it on GitHub Discussions or Discord instead of here. * If you have a question \"How Do I ...?\", please post it on GitHub Discussions or Discord instead of here.
* Could this feature be implemented as a pure Python library? If so, please open the request on the [micropython-lib repository](https://github.com/micropython/micropython-lib/issues) instead. * Could this feature be implemented as a pure Python library? If so, please open the request on the [micropython-lib repository](https://github.com/micropython/micropython-lib/issues) instead.
- type: checkboxes
#### Existing issue? id: terms
attributes:
* Please search for [existing issues](https://github.com/micropython/micropython/issues) before opening a new one. label: Checks
description: |
Before submitting your feature request, please go over these check points:
options:
- label: |
I agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone.
required: true
- label: |
I've searched for [existing issues](https://github.com/micropython/micropython/issues) regarding this feature, and didn't find any.
required: true
- type: textarea - type: textarea
id: feature id: feature
attributes: attributes:
@@ -42,32 +51,14 @@ body:
MicroPython aims to strike a balance between functionality and code size. Can this feature be optionally enabled? MicroPython aims to strike a balance between functionality and code size. Can this feature be optionally enabled?
If you believe the usefulness of this feature would outweigh the additional code size, please explain. (It's OK to say you're unsure here, we're happy to discuss this with you.) If you believe the usefulness of this feature would outweigh the additional code size, please explain. (It's OK to say you're unsure here, we're happy to discuss this with you.)
- type: dropdown - type: checkboxes
id: implementation id: implementation
attributes: attributes:
label: Implementation label: Implementation
description: |
What is your suggestion for implementing this feature?
(See also: [How to sponsor](https://github.com/sponsors/micropython#sponsors), [How to submit a Pull Request](https://github.com/micropython/micropython/wiki/ContributorGuidelines).)
options: options:
- I hope the MicroPython maintainers or community will implement this feature - label: I intend to implement this feature and would submit a Pull Request if desirable.
- I intend to implement this feature and would submit a Pull Request if desirable - label: I hope the MicroPython maintainers or community will implement this feature.
- I would like to sponsor development of this feature - label: I would like to [Sponsor](https://github.com/sponsors/micropython#sponsors) development of this feature.
multiple: true
validations:
required: true
- type: dropdown
id: code-of-conduct
attributes:
label: Code of Conduct
description: |
Do you agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone?
options:
- "Yes, I agree"
multiple: true
validations:
required: true
- type: markdown - type: markdown
attributes: attributes:
value: | value: |

View File

@@ -9,11 +9,21 @@ body:
1. For issues that are readily exploitable or have high impact, please email contact@micropython.org instead. 1. For issues that are readily exploitable or have high impact, please email contact@micropython.org instead.
1. If this is a question about security, please ask it in [Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead. 1. If this is a question about security, please ask it in [Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead.
- type: checkboxes
#### Existing issue? id: terms
attributes:
* Please search for [existing issues](https://github.com/micropython/micropython/issues) before reporting a new one. label: Checks
description: |
Before submitting your bug report, please go over these check points:
options:
- label: |
I agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone.
required: true
- label: I wish to report a specific security issue that is **not readily exploitable and does not have high impact** for MicroPython developers or users.
required: true
- label: |
I've searched for [existing issues](https://github.com/micropython/micropython/issues) and didn't find any that matched.
required: true
- type: input - type: input
id: port-board-hw id: port-board-hw
attributes: attributes:
@@ -47,14 +57,3 @@ body:
* How does the attacker exploit this issue? * How does the attacker exploit this issue?
validations: validations:
required: true required: true
- type: dropdown
id: code-of-conduct
attributes:
label: Code of Conduct
description: |
Do you agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone?
options:
- "Yes, I agree"
multiple: true
validations:
required: true

View File

@@ -1,33 +0,0 @@
<!-- Thanks for submitting a Pull Request! We appreciate you spending the
time to improve MicroPython. Please provide enough information so that
others can review your Pull Request.
Before submitting, please read:
https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md
https://github.com/micropython/micropython/wiki/ContributorGuidelines
Please check any CI failures that appear after your Pull Request is opened.
-->
### Summary
<!-- Explain the reason for making this change. What problem does the pull request
solve, or what improvement does it add? Add links if relevant. -->
### Testing
<!-- Explain what testing you did, and on which boards/ports. If there are
boards or ports that you couldn't test, please mention this here as well.
If you leave this empty then your Pull Request may be closed. -->
### Trade-offs and Alternatives
<!-- If the Pull Request has some negative impact (i.e. increased code size)
then please explain why you think the trade-off improvement is worth it.
If you can think of alternative ways to do this, please explain that here too.
Delete this heading if not relevant (i.e. small fixes) -->

View File

@@ -24,7 +24,7 @@ concurrency:
jobs: jobs:
build: build:
runs-on: ubuntu-22.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:

View File

@@ -11,7 +11,7 @@ concurrency:
jobs: jobs:
comment: comment:
runs-on: ubuntu-22.04 runs-on: ubuntu-20.04
steps: steps:
- name: 'Download artifact' - name: 'Download artifact'
id: download-artifact id: download-artifact

32
.github/workflows/ports_qemu-arm.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: qemu-arm port
on:
push:
pull_request:
paths:
- '.github/workflows/*.yml'
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/qemu-arm/**'
- 'tests/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build_and_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_qemu_arm_setup
- name: Build and run test suite
run: source tools/ci.sh && ci_qemu_arm_build
- name: Print failures
if: failure()
run: grep --before-context=100 --text "FAIL" ports/qemu-arm/build/console.out

View File

@@ -1,44 +0,0 @@
name: qemu port
on:
push:
pull_request:
paths:
- '.github/workflows/*.yml'
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/qemu/**'
- 'tests/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build_and_test_arm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_qemu_setup_arm
- name: Build and run test suite
run: source tools/ci.sh && ci_qemu_build_arm
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
build_and_test_rv32:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_qemu_setup_rv32
- name: Build and run test suite
run: source tools/ci.sh && ci_qemu_build_rv32
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures

View File

@@ -194,7 +194,7 @@ jobs:
run: tests/run-tests.py --print-failures run: tests/run-tests.py --print-failures
macos: macos:
runs-on: macos-latest runs-on: macos-11.0
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
@@ -235,17 +235,3 @@ jobs:
- name: Print failures - name: Print failures
if: failure() if: failure()
run: tests/run-tests.py --print-failures run: tests/run-tests.py --print-failures
qemu_riscv64:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_unix_qemu_riscv64_setup
- name: Build
run: source tools/ci.sh && ci_unix_qemu_riscv64_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_qemu_riscv64_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures

View File

@@ -42,8 +42,6 @@ jobs:
configuration: Debug configuration: Debug
- visualstudio: '2019' - visualstudio: '2019'
configuration: Debug configuration: Debug
env:
CI_BUILD_CONFIGURATION: ${{ matrix.configuration }}
runs-on: ${{ matrix.runner }} runs-on: ${{ matrix.runner }}
steps: steps:
- name: Install Visual Studio 2017 - name: Install Visual Studio 2017
@@ -110,6 +108,16 @@ jobs:
run: run:
shell: msys2 {0} shell: msys2 {0}
steps: steps:
- name: Get Python path
id: python_path
shell: python
run: |
import os
import sys
output = f"python={os.fspath(sys.executable)}"
print(output)
with open(os.environ["GITHUB_OUTPUT"], "w") as f:
f.write(output)
- uses: msys2/setup-msys2@v2 - uses: msys2/setup-msys2@v2
with: with:
msystem: ${{ matrix.sys }} msystem: ${{ matrix.sys }}
@@ -118,7 +126,7 @@ jobs:
make make
mingw-w64-${{ matrix.env }}-gcc mingw-w64-${{ matrix.env }}-gcc
pkg-config pkg-config
mingw-w64-${{ matrix.env }}-python3 python3
git git
diffutils diffutils
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -130,7 +138,8 @@ jobs:
run: make -C ports/windows -j2 VARIANT=${{ matrix.variant }} run: make -C ports/windows -j2 VARIANT=${{ matrix.variant }}
- name: Run tests - name: Run tests
id: test id: test
run: make -C ports/windows test_full VARIANT=${{ matrix.variant }} # msys python breaks tests so we need to use "real" windows python
run: MICROPY_CPYTHON3=$(cygpath "${{ steps.python_path.outputs.python }}") make -C ports/windows test_full VARIANT=${{ matrix.variant }}
- name: Print failures - name: Print failures
if: failure() && steps.test.conclusion == 'failure' if: failure() && steps.test.conclusion == 'failure'
working-directory: tests working-directory: tests

View File

@@ -20,15 +20,6 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: jlumbroso/free-disk-space@main
with:
# Only free up a few things so this step runs quickly.
android: false
dotnet: true
haskell: true
large-packages: false
docker-images: false
swap-storage: false
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install packages - name: Install packages
run: source tools/ci.sh && ci_zephyr_setup run: source tools/ci.sh && ci_zephyr_setup
@@ -36,8 +27,3 @@ jobs:
run: source tools/ci.sh && ci_zephyr_install run: source tools/ci.sh && ci_zephyr_install
- name: Build - name: Build
run: source tools/ci.sh && ci_zephyr_build run: source tools/ci.sh && ci_zephyr_build
- name: Run main test suite
run: source tools/ci.sh && ci_zephyr_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures

3
.gitignore vendored
View File

@@ -11,9 +11,8 @@ build/
build-*/ build-*/
docs/genrst/ docs/genrst/
# Test failure outputs and intermediate artefacts # Test failure outputs
tests/results/* tests/results/*
tests/ports/unix/ffi_lib.so
# Python cache files # Python cache files
__pycache__/ __pycache__/

2
.gitmodules vendored
View File

@@ -3,7 +3,7 @@
url = https://github.com/micropython/axtls.git url = https://github.com/micropython/axtls.git
[submodule "lib/libffi"] [submodule "lib/libffi"]
path = lib/libffi path = lib/libffi
url = https://github.com/libffi/libffi url = https://github.com/atgreen/libffi
[submodule "lib/lwip"] [submodule "lib/lwip"]
path = lib/lwip path = lib/lwip
url = https://github.com/lwip-tcpip/lwip.git url = https://github.com/lwip-tcpip/lwip.git

View File

@@ -59,6 +59,7 @@ used during the build process and is not part of the compiled source code.
/pico-sdk (BSD-3-clause) /pico-sdk (BSD-3-clause)
/re15 (BSD-3-clause) /re15 (BSD-3-clause)
/stm32lib (BSD-3-clause) /stm32lib (BSD-3-clause)
/tinytest (BSD-3-clause)
/tinyusb (MIT) /tinyusb (MIT)
/uzlib (Zlib) /uzlib (Zlib)
/wiznet5k (MIT) /wiznet5k (MIT)
@@ -72,7 +73,6 @@ used during the build process and is not part of the compiled source code.
/ppp_set_auth.* (Apache-2.0) /ppp_set_auth.* (Apache-2.0)
/rp2 /rp2
/mutex_extra.c (BSD-3-clause) /mutex_extra.c (BSD-3-clause)
/clocks_extra.c (BSD-3-clause)
/stm32 /stm32
/usbd*.c (MCD-ST Liberty SW License Agreement V2) /usbd*.c (MCD-ST Liberty SW License Agreement V2)
/stm32_it.* (MIT + BSD-3-clause) /stm32_it.* (MIT + BSD-3-clause)

View File

@@ -19,7 +19,7 @@ Python 3.5 and some select features from later versions). The following core
datatypes are provided: `str`(including basic Unicode support), `bytes`, datatypes are provided: `str`(including basic Unicode support), `bytes`,
`bytearray`, `tuple`, `list`, `dict`, `set`, `frozenset`, `array.array`, `bytearray`, `tuple`, `list`, `dict`, `set`, `frozenset`, `array.array`,
`collections.namedtuple`, classes and instances. Builtin modules include `collections.namedtuple`, classes and instances. Builtin modules include
`os`, `sys`, `time`, `re`, and `struct`, etc. Some ports have support for `os`, `sys`, `time`, `re`, and `struct`, etc. Select ports have support for
`_thread` module (multithreading), `socket` and `ssl` for networking, and `_thread` module (multithreading), `socket` and `ssl` for networking, and
`asyncio`. Note that only a subset of Python 3 functionality is implemented `asyncio`. Note that only a subset of Python 3 functionality is implemented
for the data types and modules. for the data types and modules.
@@ -35,8 +35,8 @@ DAC, PWM, SPI, I2C, CAN, Bluetooth, and USB.
Getting started Getting started
--------------- ---------------
See the [online documentation](https://docs.micropython.org/) for the API See the [online documentation](https://docs.micropython.org/) for API
reference and information about using MicroPython and information about how references and information about using MicroPython and information about how
it is implemented. it is implemented.
We use [GitHub Discussions](https://github.com/micropython/micropython/discussions) We use [GitHub Discussions](https://github.com/micropython/micropython/discussions)
@@ -108,13 +108,13 @@ track of the code size of the core runtime and VM.
In addition, the following ports are provided in this repository: In addition, the following ports are provided in this repository:
- [cc3200](ports/cc3200) -- Texas Instruments CC3200 (including PyCom WiPy). - [cc3200](ports/cc3200) -- Texas Instruments CC3200 (including PyCom WiPy).
- [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3, ESP32C6). - [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3).
- [esp8266](ports/esp8266) -- Espressif ESP8266 SoC. - [esp8266](ports/esp8266) -- Espressif ESP8266 SoC.
- [mimxrt](ports/mimxrt) -- NXP m.iMX RT (including Teensy 4.x). - [mimxrt](ports/mimxrt) -- NXP m.iMX RT (including Teensy 4.x).
- [nrf](ports/nrf) -- Nordic Semiconductor nRF51 and nRF52. - [nrf](ports/nrf) -- Nordic Semiconductor nRF51 and nRF52.
- [pic16bit](ports/pic16bit) -- Microchip PIC 16-bit. - [pic16bit](ports/pic16bit) -- Microchip PIC 16-bit.
- [powerpc](ports/powerpc) -- IBM PowerPC (including Microwatt) - [powerpc](ports/powerpc) -- IBM PowerPC (including Microwatt)
- [qemu](ports/qemu) -- QEMU-based emulated target (for testing) - [qemu-arm](ports/qemu-arm) -- QEMU-based emulated target, for testing)
- [renesas-ra](ports/renesas-ra) -- Renesas RA family. - [renesas-ra](ports/renesas-ra) -- Renesas RA family.
- [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W). - [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W).
- [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51. - [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51.

View File

@@ -59,7 +59,7 @@ A MicroPython user C module is a directory with the following files:
SRC_USERMOD_LIB_C += $(EXAMPLE_MOD_DIR)/utils/algorithm.c SRC_USERMOD_LIB_C += $(EXAMPLE_MOD_DIR)/utils/algorithm.c
Similarly, use ``SRC_USERMOD_CXX`` and ``SRC_USERMOD_LIB_CXX`` for C++ Similarly, use ``SRC_USERMOD_CXX`` and ``SRC_USERMOD_LIB_CXX`` for C++
source files. If you want to include assembly files use ``SRC_USERMOD_LIB_ASM``. source files.
If you have custom compiler options (like ``-I`` to add directories to search If you have custom compiler options (like ``-I`` to add directories to search
for header files), these should be added to ``CFLAGS_USERMOD`` for C code for header files), these should be added to ``CFLAGS_USERMOD`` for C code

View File

@@ -18,7 +18,7 @@ working with this board it may be useful to get an overview of the microcontroll
general.rst general.rst
tutorial/index.rst tutorial/index.rst
Note that there are several varieties of ESP32 -- ESP32, ESP32C3, ESP32C6, ESP32S2, ESP32S3 -- Note that there are several varieties of ESP32 -- ESP32, ESP32C3, ESP32S2, ESP32S3 --
supported by MicroPython, with some differences in functionality between them. supported by MicroPython, with some differences in functionality between them.
Installing MicroPython Installing MicroPython
@@ -61,13 +61,13 @@ The :mod:`esp32` module::
import esp32 import esp32
esp32.raw_temperature() # read the internal temperature of the MCU, in Fahrenheit esp32.raw_temperature() # read the internal temperature of the MCU, in Fahrenheit
esp32.ULP() # access to the Ultra-Low-Power Co-processor, not on ESP32C3/C6 esp32.ULP() # access to the Ultra-Low-Power Co-processor, not on ESP32C3
Note that the temperature sensor in the ESP32 will typically read higher than Note that the temperature sensor in the ESP32 will typically read higher than
ambient due to the IC getting warm while it runs. This effect can be minimised ambient due to the IC getting warm while it runs. This effect can be minimised
by reading the temperature sensor immediately after waking up from sleep. by reading the temperature sensor immediately after waking up from sleep.
ESP32C3, ESP32C6, ESP32S2, and ESP32S3 also have an internal temperature sensor available. ESP32C3, ESP32S2, and ESP32S3 also have an internal temperature sensor available.
It is implemented a bit differently to the ESP32 and returns the temperature in It is implemented a bit differently to the ESP32 and returns the temperature in
Celsius:: Celsius::
@@ -89,7 +89,7 @@ The :mod:`network` module::
wlan.isconnected() # check if the station is connected to an AP wlan.isconnected() # check if the station is connected to an AP
wlan.connect('ssid', 'key') # connect to an AP wlan.connect('ssid', 'key') # connect to an AP
wlan.config('mac') # get the interface's MAC address wlan.config('mac') # get the interface's MAC address
wlan.ipconfig('addr4') # get the interface's IPv4 addresses wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses
ap = network.WLAN(network.AP_IF) # create access-point interface ap = network.WLAN(network.AP_IF) # create access-point interface
ap.config(ssid='ESP-AP') # set the SSID of the access point ap.config(ssid='ESP-AP') # set the SSID of the access point
@@ -107,7 +107,7 @@ A useful function for connecting to your local WiFi network is::
wlan.connect('ssid', 'key') wlan.connect('ssid', 'key')
while not wlan.isconnected(): while not wlan.isconnected():
pass pass
print('network config:', wlan.ipconfig('addr4')) print('network config:', wlan.ifconfig())
Once the network is established the :mod:`socket <socket>` module can be used Once the network is established the :mod:`socket <socket>` module can be used
to create and use TCP/UDP sockets as usual, and the ``requests`` module for to create and use TCP/UDP sockets as usual, and the ``requests`` module for
@@ -130,7 +130,7 @@ To use the wired interfaces one has to specify the pins and mode ::
lan = network.LAN(mdc=PIN_MDC, ...) # Set the pin and mode configuration lan = network.LAN(mdc=PIN_MDC, ...) # Set the pin and mode configuration
lan.active(True) # activate the interface lan.active(True) # activate the interface
lan.ipconfig('addr4') # get the interface's IPv4 addresses lan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses
The keyword arguments for the constructor defining the PHY type and interface are: The keyword arguments for the constructor defining the PHY type and interface are:

View File

@@ -32,18 +32,6 @@ the prescaler of the MCPWM0 peripheral.
mem32[MCPWM0] = 0x55 # change PWM_CLK_PRESCALE mem32[MCPWM0] = 0x55 # change PWM_CLK_PRESCALE
print(hex(mem32[MCPWM0])) # read PWM_CLK_CFG_REG print(hex(mem32[MCPWM0])) # read PWM_CLK_CFG_REG
The specific addresses will be different on different ESP32
models. For example, ESP32-S3 uses these values:
.. code-block:: python3
DR_REG_DPORT_BASE = const(0x600C_0000)
DPORT_PERIP_CLK_EN0_REG = const(DR_REG_DPORT_BASE + 0x0018)
DPORT_PERIP_RST_EN0_REG = const(DR_REG_DPORT_BASE + 0x0020)
DPORT_PWM0_CLK_EN = const(1 << 17)
MCPWM0 = const(0x6001_E000 + 0x0004)
...
Note that before a peripheral can be used its clock must be enabled and it must Note that before a peripheral can be used its clock must be enabled and it must
be taken out of reset. In the above example the following registers are used be taken out of reset. In the above example the following registers are used
for this: for this:

View File

@@ -59,7 +59,7 @@ The :mod:`network` module::
wlan.isconnected() # check if the station is connected to an AP wlan.isconnected() # check if the station is connected to an AP
wlan.connect('ssid', 'key') # connect to an AP wlan.connect('ssid', 'key') # connect to an AP
wlan.config('mac') # get the interface's MAC address wlan.config('mac') # get the interface's MAC address
wlan.ipconfig('addr4') # get the interface's IPv4 addresses wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses
ap = network.WLAN(network.AP_IF) # create access-point interface ap = network.WLAN(network.AP_IF) # create access-point interface
ap.active(True) # activate the interface ap.active(True) # activate the interface
@@ -76,7 +76,7 @@ A useful function for connecting to your local WiFi network is::
wlan.connect('ssid', 'key') wlan.connect('ssid', 'key')
while not wlan.isconnected(): while not wlan.isconnected():
pass pass
print('network config:', wlan.ipconfig('addr4')) print('network config:', wlan.ifconfig())
Once the network is established the :mod:`socket <socket>` module can be used Once the network is established the :mod:`socket <socket>` module can be used
to create and use TCP/UDP sockets as usual. to create and use TCP/UDP sockets as usual.

View File

@@ -19,10 +19,10 @@ You can check if the interfaces are active by::
You can also check the network settings of the interface by:: You can also check the network settings of the interface by::
>>> ap_if.ipconfig('addr4') >>> ap_if.ifconfig()
('192.168.4.1', '255.255.255.0') ('192.168.4.1', '255.255.255.0', '192.168.4.1', '8.8.8.8')
The returned values are: IP address and netmask. The returned values are: IP address, netmask, gateway, DNS.
Configuration of the WiFi Configuration of the WiFi
------------------------- -------------------------
@@ -45,8 +45,8 @@ To check if the connection is established use::
Once established you can check the IP address:: Once established you can check the IP address::
>>> sta_if.ipconfig('addr4') >>> sta_if.ifconfig()
('192.168.0.2', '255.255.255.0') ('192.168.0.2', '255.255.255.0', '192.168.0.1', '8.8.8.8')
You can then disable the access-point interface if you no longer need it:: You can then disable the access-point interface if you no longer need it::
@@ -64,7 +64,7 @@ connect to your WiFi network::
sta_if.connect('<ssid>', '<key>') sta_if.connect('<ssid>', '<key>')
while not sta_if.isconnected(): while not sta_if.isconnected():
pass pass
print('network config:', sta_if.ipconfig('addr4')) print('network config:', sta_if.ifconfig())
Sockets Sockets
------- -------

View File

@@ -82,10 +82,6 @@ Functions and types
In MicroPython, `byteorder` parameter must be positional (this is In MicroPython, `byteorder` parameter must be positional (this is
compatible with CPython). compatible with CPython).
.. note:: The optional ``signed`` kwarg from CPython is not supported.
MicroPython currently converts negative integers as signed,
and positive as unsigned. (:ref:`Details <cpydiff_types_int_to_bytes>`.)
.. function:: isinstance() .. function:: isinstance()
.. function:: issubclass() .. function:: issubclass()

View File

@@ -238,12 +238,6 @@ The following methods are not part of the core Pin API and only implemented on c
Availability: cc3200 port. Availability: cc3200 port.
.. method:: Pin.toggle()
Toggle output pin from "0" to "1" or vice-versa.
Availability: mimxrt, samd, rp2 ports.
Constants Constants
--------- ---------

View File

@@ -152,6 +152,31 @@ Methods
Send a break condition on the bus. This drives the bus low for a duration Send a break condition on the bus. This drives the bus low for a duration
longer than required for a normal transmission of a character. longer than required for a normal transmission of a character.
.. method:: UART.irq(trigger, priority=1, handler=None, wake=machine.IDLE)
Create a callback to be triggered when data is received on the UART.
- *trigger* can only be ``UART.RX_ANY``
- *priority* level of the interrupt. Can take values in the range 1-7.
Higher values represent higher priorities.
- *handler* an optional function to be called when new characters arrive.
- *wake* can only be ``machine.IDLE``.
.. note::
The handler will be called whenever any of the following two conditions are met:
- 8 new characters have been received.
- At least 1 new character is waiting in the Rx buffer and the Rx line has been
silent for the duration of 1 complete frame.
This means that when the handler function is called there will be between 1 to 8
characters waiting.
Returns an irq object.
Availability: WiPy.
.. method:: UART.flush() .. method:: UART.flush()
Waits until all data has been sent. In case of a timeout, an exception is raised. The timeout Waits until all data has been sent. In case of a timeout, an exception is raised. The timeout
@@ -160,7 +185,7 @@ Methods
.. note:: .. note::
For the esp8266 and nrf ports the call returns while the last byte is sent. For the rp2, esp8266 and nrf ports the call returns while the last byte is sent.
If required, a one character wait time has to be added in the calling script. If required, a one character wait time has to be added in the calling script.
Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra
@@ -172,91 +197,17 @@ Methods
.. note:: .. note::
For the esp8266 and nrf ports the call may return ``True`` even if the last byte For the rp2, esp8266 and nrf ports the call may return ``True`` even if the last byte
of a transfer is still being sent. If required, a one character wait time has to be of a transfer is still being sent. If required, a one character wait time has to be
added in the calling script. added in the calling script.
Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra
.. method:: UART.irq(handler=None, trigger=0, hard=False)
Configure an interrupt handler to be called when a UART event occurs.
The arguments are:
- *handler* is an optional function to be called when the interrupt event
triggers. The handler must take exactly one argument which is the
``UART`` instance.
- *trigger* configures the event(s) which can generate an interrupt.
Possible values are a mask of one or more of the following:
- ``UART.IRQ_RXIDLE`` interrupt after receiving at least one character
and then the RX line goes idle.
- ``UART.IRQ_RX`` interrupt after each received character.
- ``UART.IRQ_TXIDLE`` interrupt after or while the last character(s) of
a message are or have been sent.
- ``UART.IRQ_BREAK`` interrupt when a break state is detected at RX
- *hard* if true a hardware interrupt is used. This reduces the delay
between the pin change and the handler being called. Hard interrupt
handlers may not allocate memory; see :ref:`isr_rules`.
Returns an irq object.
Due to limitations of the hardware not all trigger events are available on all ports.
.. table:: Availability of triggers
:align: center
============== ========== ====== ========== =========
Port / Trigger IRQ_RXIDLE IRQ_RX IRQ_TXIDLE IRQ_BREAK
============== ========== ====== ========== =========
CC3200 yes
ESP32 yes yes yes
MIMXRT yes yes
NRF yes yes
RENESAS-RA yes yes
RP2 yes yes yes
SAMD yes yes yes
STM32 yes yes
============== ========== ====== ========== =========
.. note::
- The ESP32 port does not support the option hard=True.
- The rp2 port's UART.IRQ_TXIDLE is only triggered when the message
is longer than 5 characters and the trigger happens when still 5 characters
are to be sent.
- The rp2 port's UART.IRQ_BREAK needs receiving valid characters for triggering
again.
- The SAMD port's UART.IRQ_TXIDLE is triggered while the last character is sent.
- On STM32F4xx MCU's, using the trigger UART.IRQ_RXIDLE the handler will be called once
after the first character and then after the end of the message, when the line is
idle.
Availability: cc3200, esp32, mimxrt, nrf, renesas-ra, rp2, samd, stm32.
Constants Constants
--------- ---------
.. data:: UART.RTS .. data:: UART.RX_ANY
UART.CTS
Flow control options. IRQ trigger sources
Availability: esp32, mimxrt, renesas-ra, rp2, stm32. Availability: WiPy.
.. data:: UART.IRQ_RXIDLE
UART.IRQ_RX
UART.IRQ_TXIDLE
UART.IRQ_BREAK
IRQ trigger sources.
Availability: renesas-ra, stm32, esp32, rp2040, mimxrt, samd, cc3200.

View File

@@ -215,13 +215,6 @@ Methods
drivers. Placing a different string at any of these indexes overrides that drivers. Placing a different string at any of these indexes overrides that
string in the built-in driver. string in the built-in driver.
.. method:: USBDevice.remote_wakeup(self)
Wake up host if we are in suspend mode and the REMOTE_WAKEUP feature
is enabled by the host. This has to be enabled in the USB attributes,
and on the host. Returns ``True`` if remote wakeup was enabled and
active and the host was woken up.
.. method:: USBDevice.submit_xfer(self, ep, buffer /) .. method:: USBDevice.submit_xfer(self, ep, buffer /)
Submit a USB transfer on endpoint number ``ep``. ``buffer`` must be Submit a USB transfer on endpoint number ``ep``. ``buffer`` must be

View File

@@ -127,20 +127,14 @@ Power related functions
.. function:: idle() .. function:: idle()
Gates the clock to the CPU, useful to reduce power consumption at any time Gates the clock to the CPU, useful to reduce power consumption at any time during
during short or long periods. Peripherals continue working and execution short or long periods. Peripherals continue working and execution resumes as soon
resumes as soon as any interrupt is triggered, or at most one millisecond as any interrupt is triggered (on many ports this includes system timer
after the CPU was paused. interrupt occurring at regular intervals on the order of millisecond).
It is recommended to call this function inside any tight loop that is
continuously checking for an external change (i.e. polling). This will reduce
power consumption without significantly impacting performance. To reduce
power consumption further then see the :func:`lightsleep`,
:func:`time.sleep()` and :func:`time.sleep_ms()` functions.
.. function:: sleep() .. function:: sleep()
.. note:: This function is deprecated, use :func:`lightsleep()` instead with no arguments. .. note:: This function is deprecated, use `lightsleep()` instead with no arguments.
.. function:: lightsleep([time_ms]) .. function:: lightsleep([time_ms])
deepsleep([time_ms]) deepsleep([time_ms])

View File

@@ -125,11 +125,8 @@ Functions
Return the natural logarithm of the gamma function of ``x``. Return the natural logarithm of the gamma function of ``x``.
.. function:: log(x) .. function:: log(x)
log(x, base)
With one argument, return the natural logarithm of *x*. Return the natural logarithm of ``x``.
With two arguments, return the logarithm of *x* to the given *base*.
.. function:: log10(x) .. function:: log10(x)

View File

@@ -136,14 +136,6 @@ Functions
the heap may be locked) and scheduling a function to call later will lift the heap may be locked) and scheduling a function to call later will lift
those restrictions. those restrictions.
On multi-threaded ports, the scheduled function's behaviour depends on
whether the Global Interpreter Lock (GIL) is enabled for the specific port:
- If GIL is enabled, the function can preempt any thread and run in its
context.
- If GIL is disabled, the function will only preempt the main thread and run
in its context.
Note: If `schedule()` is called from a preempting IRQ, when memory Note: If `schedule()` is called from a preempting IRQ, when memory
allocation is not allowed and the callback to be passed to `schedule()` is allocation is not allowed and the callback to be passed to `schedule()` is
a bound method, passing this directly will fail. This is because creating a a bound method, passing this directly will fail. This is because creating a
@@ -155,71 +147,3 @@ Functions
There is a finite queue to hold the scheduled functions and `schedule()` There is a finite queue to hold the scheduled functions and `schedule()`
will raise a `RuntimeError` if the queue is full. will raise a `RuntimeError` if the queue is full.
Classes
-------
.. class:: RingIO(size)
.. class:: RingIO(buffer)
:noindex:
Provides a fixed-size ringbuffer for bytes with a stream interface. Can be
considered like a fifo queue variant of `io.BytesIO`.
When created with integer size a suitable buffer will be allocated.
Alternatively a `bytearray` or similar buffer protocol object can be provided
to the constructor for in-place use.
The classic ringbuffer algorithm is used which allows for any size buffer
to be used however one byte will be consumed for tracking. If initialised
with an integer size this will be accounted for, for example ``RingIO(16)``
will allocate a 17 byte buffer internally so it can hold 16 bytes of data.
When passing in a pre-allocated buffer however one byte less than its
original length will be available for storage, eg. ``RingIO(bytearray(16))``
will only hold 15 bytes of data.
A RingIO instance can be IRQ / thread safe when used to pass data in a single
direction eg. when written to in an IRQ and read from in a non-IRQ function
(or vice versa). This does not hold if you try to eg. write to a single instance
from both IRQ and non-IRQ code, this would often cause data corruption.
.. method:: RingIO.any()
Returns an integer counting the number of characters that can be read.
.. method:: RingIO.read([nbytes])
Read available characters. This is a non-blocking function. If ``nbytes``
is specified then read at most that many bytes, otherwise read as much
data as possible.
Return value: a bytes object containing the bytes read. Will be
zero-length bytes object if no data is available.
.. method:: RingIO.readline([nbytes])
Read a line, ending in a newline character or return if one exists in
the buffer, else return available bytes in buffer. If ``nbytes`` is
specified then read at most that many bytes.
Return value: a bytes object containing the line read.
.. method:: RingIO.readinto(buf[, nbytes])
Read available bytes into the provided ``buf``. If ``nbytes`` is
specified then read at most that many bytes. Otherwise, read at
most ``len(buf)`` bytes.
Return value: Integer count of the number of bytes read into ``buf``.
.. method:: RingIO.write(buf)
Non-blocking write of bytes from ``buf`` into the ringbuffer, limited
by the available space in the ringbuffer.
Return value: Integer count of bytes written.
.. method:: RingIO.close()
No-op provided as part of standard `stream` interface. Has no effect
on data in the ringbuffer.

View File

@@ -43,8 +43,7 @@ Constructors
- *pin* is a machine.Pin instance. - *pin* is a machine.Pin instance.
- *n* is the number of LEDs in the strip. - *n* is the number of LEDs in the strip.
- *bpp* is 3 for RGB LEDs, and 4 for RGBW LEDs. - *bpp* is 3 for RGB LEDs, and 4 for RGBW LEDs.
- *timing* is 0 for 400KHz, and 1 for 800kHz LEDs (most are 800kHz). You - *timing* is 0 for 400KHz, and 1 for 800kHz LEDs (most are 800kHz).
may also supply a timing tuple as accepted by `machine.bitstream()`.
Pixel access methods Pixel access methods
-------------------- --------------------

View File

@@ -10,7 +10,7 @@ Example usage::
import network import network
nic = network.LAN(0) nic = network.LAN(0)
print(nic.ipconfig("addr4")) print(nic.ifconfig())
# now use socket as usual # now use socket as usual
... ...

View File

@@ -1,98 +0,0 @@
.. currentmodule:: network
.. _network.PPP:
class PPP -- create network connections over serial PPP
=======================================================
This class allows you to create a network connection over a serial port using
the PPP protocol. It is only available on selected ports and boards.
Example usage::
import network
ppp = network.PPP(uart)
ppp.connect()
while not ppp.isconnected():
pass
print(ppp.ipconfig("addr4"))
# use the socket module as usual, etc
ppp.disconnect()
Constructors
------------
.. class:: PPP(stream)
Create a PPP driver object.
Arguments are:
- *stream* is any object that supports the stream protocol, but is most commonly a
:class:`machine.UART` instance. This stream object must have an ``irq()`` method
and an ``IRQ_RXIDLE`` constant, for use by `PPP.connect`.
Methods
-------
.. method:: PPP.connect(security=SEC_NONE, user=None, key=None)
Initiate a PPP connection with the given parameters:
- *security* is the type of security, either ``PPP.SEC_NONE``, ``PPP.SEC_PAP``,
or ``PPP.SEC_CHAP``.
- *user* is an optional user name to use with the security mode.
- *key* is an optional password to use with the security mode.
When this method is called the underlying stream has its interrupt configured to call
`PPP.poll` via ``stream.irq(ppp.poll, stream.IRQ_RXIDLE)``. This makes sure the
stream is polled, and data passed up the PPP stack, wheverver data becomes available
on the stream.
The connection proceeds asynchronously, in the background.
.. method:: PPP.disconnect()
Terminate the connection. This must be called to cleanly close the PPP connection.
.. method:: PPP.isconnected()
Returns ``True`` if the PPP link is connected and up.
Returns ``False`` otherwise.
.. method:: PPP.status()
Returns the PPP status.
.. method:: PPP.config(config_parameters)
Sets or gets parameters of the PPP interface. There are currently no parameter that
can be set or retrieved.
.. method:: PPP.ipconfig('param')
PPP.ipconfig(param=value, ...)
See `AbstractNIC.ipconfig`.
.. method:: PPP.ifconfig([(ip, subnet, gateway, dns)])
See `AbstractNIC.ifconfig`.
.. method:: PPP.poll()
Poll the underlying stream for data, and pass it up the PPP stack.
This is called automatically if the stream is a UART with a RXIDLE interrupt,
so it's not usually necessary to call it manually.
Constants
---------
.. data:: PPP.SEC_NONE
PPP.SEC_PAP
PPP.SEC_CHAP
The type of connection security.

View File

@@ -13,7 +13,7 @@ Example usage::
import network import network
nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4) nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4)
print(nic.ipconfig("addr4")) print(nic.ifconfig())
# now use socket as usual # now use socket as usual
... ...
@@ -51,7 +51,20 @@ Constructors
Methods Methods
------- -------
This class implements most methods from `AbstractNIC <AbstractNIC>`, which are documented there. Additional methods are: .. method:: WIZNET5K.isconnected()
Returns ``True`` if the physical Ethernet link is connected and up.
Returns ``False`` otherwise.
.. method:: WIZNET5K.ifconfig([(ip, subnet, gateway, dns)])
Get/set IP address, subnet mask, gateway and DNS.
When called with no arguments, this method returns a 4-tuple with the above information.
To set the above values, pass a 4-tuple with the required information. For example::
nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
.. method:: WIZNET5K.regs() .. method:: WIZNET5K.regs()

View File

@@ -107,7 +107,7 @@ Methods
Get or set general network interface parameters. These methods allow to work Get or set general network interface parameters. These methods allow to work
with additional parameters beyond standard IP configuration (as dealt with by with additional parameters beyond standard IP configuration (as dealt with by
`AbstractNIC.ipconfig()`). These include network-specific and hardware-specific `WLAN.ifconfig()`). These include network-specific and hardware-specific
parameters. For setting parameters, keyword argument syntax should be used, parameters. For setting parameters, keyword argument syntax should be used,
multiple parameters can be set at once. For querying, parameters name should multiple parameters can be set at once. For querying, parameters name should
be quoted as a string, and only one parameter can be queries at time:: be quoted as a string, and only one parameter can be queries at time::

View File

@@ -20,7 +20,7 @@ This class provides a driver for the WiFi network processor in the WiPy. Example
wlan.connect('your-ssid', auth=(WLAN.WPA2, 'your-key')) wlan.connect('your-ssid', auth=(WLAN.WPA2, 'your-key'))
while not wlan.isconnected(): while not wlan.isconnected():
time.sleep_ms(50) time.sleep_ms(50)
print(wlan.ipconfig("addr4")) print(wlan.ifconfig())
# now use socket as usual # now use socket as usual
... ...
@@ -96,10 +96,16 @@ Methods
In case of STA mode, returns ``True`` if connected to a WiFi access point and has a valid IP address. In case of STA mode, returns ``True`` if connected to a WiFi access point and has a valid IP address.
In AP mode returns ``True`` when a station is connected, ``False`` otherwise. In AP mode returns ``True`` when a station is connected, ``False`` otherwise.
.. method:: WLANWiPy.ipconfig('param') .. method:: WLANWiPy.ifconfig(if_id=0, config=['dhcp' or configtuple])
WLANWiPy.ipconfig(param=value, ...)
See :meth:`AbstractNIC.ipconfig <AbstractNIC.ipconfig>`. Supported parameters are: ``dhcp4``, ``addr4``, ``gw4``. With no parameters given returns a 4-tuple of *(ip, subnet_mask, gateway, DNS_server)*.
if ``'dhcp'`` is passed as a parameter then the DHCP client is enabled and the IP params
are negotiated with the AP.
If the 4-tuple config is given then a static IP is configured. For instance::
wlan.ifconfig(config=('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
.. method:: WLANWiPy.mode([mode]) .. method:: WLANWiPy.mode([mode])

View File

@@ -24,7 +24,7 @@ For example::
print("Waiting for connection...") print("Waiting for connection...")
while not nic.isconnected(): while not nic.isconnected():
time.sleep(1) time.sleep(1)
print(nic.ipconfig("addr4")) print(nic.ifconfig())
# now use socket as usual # now use socket as usual
import socket import socket
@@ -113,48 +113,8 @@ parameter should be `id`.
connected to the AP. The list contains tuples of the form connected to the AP. The list contains tuples of the form
(MAC, RSSI). (MAC, RSSI).
.. method:: AbstractNIC.ipconfig('param')
AbstractNIC.ipconfig(param=value, ...)
Get or set interface-specific IP-configuration interface parameters.
Supported parameters are the following (availability of a particular
parameter depends on the port and the specific network interface):
* ``dhcp4`` (``True/False``) obtain an IPv4 address, gateway and dns
server via DHCP. This method does not block and wait for an address
to be obtained. To check if an address was obtained, use the read-only
property ``has_dhcp4``.
* ``gw4`` Get/set the IPv4 default-gateway.
* ``dhcp6`` (``True/False``) obtain a DNS server via stateless DHCPv6.
Obtaining IP Addresses via DHCPv6 is currently not implemented.
* ``autoconf6`` (``True/False``) obtain a stateless IPv6 address via
the network prefix shared in router advertisements. To check if a
stateless address was obtained, use the read-only
property ``has_autoconf6``.
* ``addr4`` (e.g. ``192.168.0.4/24``) obtain the current IPv4 address
and network mask as ``(ip, subnet)``-tuple, regardless of how this
address was obtained. This method can be used to set a static IPv4
address either as ``(ip, subnet)``-tuple or in CIDR-notation.
* ``addr6`` (e.g. ``fe80::1234:5678``) obtain a list of current IPv6
addresses as ``(ip, state, preferred_lifetime, valid_lifetime)``-tuple.
This include link-local, slaac and static addresses.
``preferred_lifetime`` and ``valid_lifetime`` represent the remaining
valid and preferred lifetime of each IPv6 address, in seconds.
``state`` indicates the current state of the address:
* ``0x08`` - ``0x0f`` indicates the address is tentative, counting the
number of probes sent.
* ``0x10`` The address is deprecated (but still valid)
* ``0x30`` The address is preferred (and valid)
* ``0x40`` The address is duplicated and can not be used.
This method can be used to set a static IPv6
address, by setting this parameter to the address, like ``fe80::1234:5678``.
.. method:: AbstractNIC.ifconfig([(ip, subnet, gateway, dns)]) .. method:: AbstractNIC.ifconfig([(ip, subnet, gateway, dns)])
.. note:: This function is deprecated, use `ipconfig()` instead.
Get/set IP-level network interface parameters: IP address, subnet mask, Get/set IP-level network interface parameters: IP address, subnet mask,
gateway and DNS server. When called with no arguments, this method returns gateway and DNS server. When called with no arguments, this method returns
a 4-tuple with the above information. To set the above values, pass a a 4-tuple with the above information. To set the above values, pass a
@@ -167,7 +127,7 @@ parameter should be `id`.
Get or set general network interface parameters. These methods allow to work Get or set general network interface parameters. These methods allow to work
with additional parameters beyond standard IP configuration (as dealt with by with additional parameters beyond standard IP configuration (as dealt with by
`ipconfig()`). These include network-specific and hardware-specific `ifconfig()`). These include network-specific and hardware-specific
parameters. For setting parameters, the keyword argument parameters. For setting parameters, the keyword argument
syntax should be used, and multiple parameters can be set at once. For syntax should be used, and multiple parameters can be set at once. For
querying, a parameter name should be quoted as a string, and only one querying, a parameter name should be quoted as a string, and only one
@@ -192,7 +152,6 @@ provide a way to control networking interfaces of various kinds.
network.WLANWiPy.rst network.WLANWiPy.rst
network.WIZNET5K.rst network.WIZNET5K.rst
network.LAN.rst network.LAN.rst
network.PPP.rst
Network functions Network functions
================= =================
@@ -236,20 +195,6 @@ The following are functions available in the network module.
The default hostname is typically the name of the board. The default hostname is typically the name of the board.
.. function:: ipconfig('param')
ipconfig(param=value, ...)
Get or set global IP-configuration parameters.
Supported parameters are the following (availability of a particular
parameter depends on the port and the specific network interface):
* ``dns`` Get/set DNS server. This method can support both, IPv4 and
IPv6 addresses.
* ``prefer`` (``4/6``) Specify which address type to return, if a domain
name has both A and AAAA records. Note, that this does not clear the
local DNS cache, so that any previously obtained addresses might not
change.
.. function:: phy_mode([mode]) .. function:: phy_mode([mode])
Get or set the PHY mode. Get or set the PHY mode.

View File

@@ -27,17 +27,6 @@ Constructors
Methods Methods
------- -------
.. method:: PIO.gpio_base([base])
Query and optionally set the current GPIO base for this PIO instance.
If an argument is given then it must be a pin (or integer corresponding to a pin
number), restricted to either GPIO0 or GPIO16. The GPIO base will then be set to
that pin. Setting the GPIO base must be done before any programs are added or state
machines created.
Returns the current GPIO base pin.
.. method:: PIO.add_program(program) .. method:: PIO.add_program(program)
Add the *program* to the instruction memory of this PIO instance. Add the *program* to the instruction memory of this PIO instance.

View File

@@ -438,10 +438,6 @@ The i.MXRT MCU supports battery backup of the RTC. By connecting a battery of
current drawn from the battery is ~20µA, which is rather high. A CR2032 coin current drawn from the battery is ~20µA, which is rather high. A CR2032 coin
cell will last for about one year. cell will last for about one year.
Note: In v1.23.0 the support for subseconds was removed. When reading the RTC, 0 will
be returned as value for subsecond, When setting the RTC time, the subsecond
field is ignored. The RTC itself does not provide a microsecond value.
SD card SD card
------- -------
@@ -532,7 +528,7 @@ Ethernet. Example usage::
lan.active(True) lan.active(True)
If there is a DHCP server in the LAN, the IP address is supplied by that server. If there is a DHCP server in the LAN, the IP address is supplied by that server.
Otherwise, the IP address can be set with lan.ipconfig(addr4="..."). The default address Otherwise, the IP address can be set with lan.ifconfig(). The default address
is 192.168.0.1. is 192.168.0.1.
Teensy 4.1 does not have an Ethernet jack on the board, but PJRC offers an Teensy 4.1 does not have an Ethernet jack on the board, but PJRC offers an

View File

@@ -227,12 +227,11 @@ The full list of supported commands are:
- ``cat <file..>`` to show the contents of a file or files on the device - ``cat <file..>`` to show the contents of a file or files on the device
- ``ls`` to list the current directory - ``ls`` to list the current directory
- ``ls <dirs...>`` to list the given directories - ``ls <dirs...>`` to list the given directories
- ``cp [-rf] <src...> <dest>`` to copy files - ``cp [-r] <src...> <dest>`` to copy files
- ``rm <src...>`` to remove files on the device - ``rm <src...>`` to remove files on the device
- ``mkdir <dirs...>`` to create directories on the device - ``mkdir <dirs...>`` to create directories on the device
- ``rmdir <dirs...>`` to remove directories on the device - ``rmdir <dirs...>`` to remove directories on the device
- ``touch <file..>`` to create the files (if they don't already exist) - ``touch <file..>`` to create the files (if they don't already exist)
- ``sha256sum <file..>`` to calculate the SHA256 sum of files
The ``cp`` command uses a convention where a leading ``:`` represents a remote The ``cp`` command uses a convention where a leading ``:`` represents a remote
path. Without a leading ``:`` means a local path. This is based on the path. Without a leading ``:`` means a local path. This is based on the
@@ -257,11 +256,6 @@ The full list of supported commands are:
This will copy the file to the device then enter the REPL. The ``+`` prevents This will copy the file to the device then enter the REPL. The ``+`` prevents
``"repl"`` being interpreted as a path. ``"repl"`` being interpreted as a path.
The ``cp`` command supports the ``-r`` option to make a recursive copy. By
default ``cp`` will skip copying files to the remote device if the SHA256 hash
of the source and destination file matches. To force a copy regardless of the
hash use the ``-f`` option.
**Note:** For convenience, all of the filesystem sub-commands are also **Note:** For convenience, all of the filesystem sub-commands are also
:ref:`aliased as regular commands <mpremote_shortcuts>`, i.e. you can write :ref:`aliased as regular commands <mpremote_shortcuts>`, i.e. you can write
``mpremote cp ...`` instead of ``mpremote fs cp ...``. ``mpremote cp ...`` instead of ``mpremote fs cp ...``.
@@ -475,9 +469,9 @@ An example ``config.py`` might look like:
for ap in wl.scan(): for ap in wl.scan():
print(ap) print(ap)
""",], # Print out nearby WiFi networks. """,], # Print out nearby WiFi networks.
"wl_ipconfig": [ "wl_ifconfig": [
"exec", "exec",
"import network; sta_if = network.WLAN(network.STA_IF); print(sta_if.ipconfig('addr4'))", "import network; sta_if = network.WLAN(network.STA_IF); print(sta_if.ifconfig())",
""",], # Print ip address of station interface. """,], # Print ip address of station interface.
"test": ["mount", ".", "exec", "import test"], # Mount current directory and run test.py. "test": ["mount", ".", "exec", "import test"], # Mount current directory and run test.py.
"demo": ["run", "path/to/demo.py"], # Execute demo.py on the device. "demo": ["run", "path/to/demo.py"], # Execute demo.py on the device.

View File

@@ -58,7 +58,7 @@ If importing an .mpy file fails then try the following:
sys_mpy = sys.implementation._mpy sys_mpy = sys.implementation._mpy
arch = [None, 'x86', 'x64', arch = [None, 'x86', 'x64',
'armv6', 'armv6m', 'armv7m', 'armv7em', 'armv7emsp', 'armv7emdp', 'armv6', 'armv6m', 'armv7m', 'armv7em', 'armv7emsp', 'armv7emdp',
'xtensa', 'xtensawin', 'rv32imc'][sys_mpy >> 10] 'xtensa', 'xtensawin'][sys_mpy >> 10]
print('mpy version:', sys_mpy & 0xff) print('mpy version:', sys_mpy & 0xff)
print('mpy sub-version:', sys_mpy >> 8 & 3) print('mpy sub-version:', sys_mpy >> 8 & 3)
print('mpy flags:', end='') print('mpy flags:', end='')

View File

@@ -120,8 +120,9 @@ Some more examples::
# Same, but using . instead. # Same, but using . instead.
$ pyboard.py --device /dev/ttyACM0 -f cp :main.py . $ pyboard.py --device /dev/ttyACM0 -f cp :main.py .
# Copy three files to the device, keeping their names. # Copy three files to the device, keeping their names
$ pyboard.py --device /dev/ttyACM0 -f cp main.py app.py foo.py : # and paths (note: `lib` must exist on the device)
$ pyboard.py --device /dev/ttyACM0 -f cp main.py app.py lib/foo.py :
# Remove a file from the device. # Remove a file from the device.
$ pyboard.py --device /dev/ttyACM0 -f rm util.py $ pyboard.py --device /dev/ttyACM0 -f rm util.py

View File

@@ -31,25 +31,12 @@ The MicroPython REPL is accessed via the USB serial port. Tab-completion is usef
find out what methods an object has. Paste mode (ctrl-E) is useful to paste a find out what methods an object has. Paste mode (ctrl-E) is useful to paste a
large slab of Python code into the REPL. large slab of Python code into the REPL.
The :mod:`machine` module: The :mod:`machine` module::
machine.freq() allows to change the MCU frequency and control the peripheral
frequency for UART and SPI. Usage::
machine.freq(MCU_frequency[, peripheral_frequency=48_000_000])
The MCU frequency can be set in a range from less than 48 MHz to about 250MHz.
The default at boot time is 125 MHz. The peripheral frequency must be either
48 MHz or identical to the MCU frequency, with 48 MHz as the default.
If the peripheral frequency is changed, any already existing instance of
UART and SPI will change it's baud rate and may have to be re-configured::
import machine import machine
machine.freq() # get the current frequency of the CPU machine.freq() # get the current frequency of the CPU
machine.freq(240000000) # set the CPU frequency to 240 MHz and keep machine.freq(240000000) # set the CPU frequency to 240 MHz
# the UART frequency at 48MHz
machine.freq(125000000, 125000000) # set the CPU and UART frequency to 125 MHz
The :mod:`rp2` module:: The :mod:`rp2` module::
@@ -200,14 +187,6 @@ Use the :ref:`machine.ADC <machine.ADC>` class::
adc = ADC(Pin(26)) # create ADC object on ADC pin adc = ADC(Pin(26)) # create ADC object on ADC pin
adc.read_u16() # read value, 0-65535 across voltage range 0.0v - 3.3v adc.read_u16() # read value, 0-65535 across voltage range 0.0v - 3.3v
The argument of the constructor ADC specifies either a Pin by number, name of as
Pin object, or a channel number in the range 0 - 3 or ADC.CORE_TEMP for the
internal temperature sensor. If a pin is specified,
the pin is initialized in high-Z mode. If a channel number is used, the pin
is not initialized and configuring is left to the user code. After hard reset,
RP2040 pins operate in current sink mode at about 60µA. If the pin is not
otherwise configured, that may lead to wrong ADC readings.
Software SPI bus Software SPI bus
---------------- ----------------

View File

@@ -65,8 +65,6 @@ Use the :mod:`time <time>` module::
start = time.ticks_ms() # get millisecond counter start = time.ticks_ms() # get millisecond counter
delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference
Note that :func:`time.sleep_us()` delays by busy waiting. During that time, other tasks are
not scheduled.
Clock and time Clock and time
-------------- --------------

View File

@@ -184,18 +184,18 @@ WLAN (WiFi)
See :ref:`network.WLAN <network.WLAN>` and :mod:`machine`. :: See :ref:`network.WLAN <network.WLAN>` and :mod:`machine`. ::
import machine, network import machine
from network import WLAN from network import WLAN
# configure the WLAN subsystem in station mode (the default is AP) # configure the WLAN subsystem in station mode (the default is AP)
wlan = WLAN(mode=WLAN.STA) wlan = WLAN(mode=WLAN.STA)
# go for fixed IP settings # go for fixed IP settings
network.ipconfig(dns='8.8.8.8') wlan.ifconfig(config=('192.168.0.107', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
wlan.ipconfig(addr4='192.168.0.107/24', gw4='192.168.0.1')
wlan.scan() # scan for available networks wlan.scan() # scan for available networks
wlan.connect(ssid='mynetwork', auth=(WLAN.WPA2, 'mynetworkkey')) wlan.connect(ssid='mynetwork', auth=(WLAN.WPA2, 'mynetworkkey'))
while not wlan.isconnected(): while not wlan.isconnected():
pass pass
print(wlan.ifconfig())
# enable wake on WLAN # enable wake on WLAN
wlan.irq(trigger=WLAN.ANY_EVENT, wake=machine.SLEEP) wlan.irq(trigger=WLAN.ANY_EVENT, wake=machine.SLEEP)
# go to sleep # go to sleep

View File

@@ -50,15 +50,14 @@ Assigning a static IP address when booting
If you want your WiPy to connect to your home router after boot-up, and with a fixed If you want your WiPy to connect to your home router after boot-up, and with a fixed
IP address so that you can access it via telnet or FTP, use the following script as /flash/boot.py:: IP address so that you can access it via telnet or FTP, use the following script as /flash/boot.py::
import machine, network import machine
from network import WLAN from network import WLAN
wlan = WLAN() # get current object, without changing the mode wlan = WLAN() # get current object, without changing the mode
if machine.reset_cause() != machine.SOFT_RESET: if machine.reset_cause() != machine.SOFT_RESET:
wlan.init(WLAN.STA) wlan.init(WLAN.STA)
# configuration below MUST match your home router settings!! # configuration below MUST match your home router settings!!
network.ipconfig(dns='8.8.8.8') wlan.ifconfig(config=('192.168.178.107', '255.255.255.0', '192.168.178.1', '8.8.8.8'))
wlan.ipconfig(addr4='192.168.0.107/24', gw4='192.168.0.1')
if not wlan.isconnected(): if not wlan.isconnected():
# change the line below to match your network ssid, security and password # change the line below to match your network ssid, security and password

View File

@@ -36,7 +36,7 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
from machine import Pin from machine import Pin
pin = Pin(("gpiob", 21), Pin.IN) # create input pin on GPIO port B pin = Pin(("GPIO_1", 21), Pin.IN) # create input pin on GPIO1
print(pin) # print pin port and number print(pin) # print pin port and number
pin.init(Pin.OUT, Pin.PULL_UP, value=1) # reinitialize pin pin.init(Pin.OUT, Pin.PULL_UP, value=1) # reinitialize pin
@@ -47,14 +47,14 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
pin.on() # set pin to high pin.on() # set pin to high
pin.off() # set pin to low pin.off() # set pin to low
pin = Pin(("gpiob", 21), Pin.IN) # create input pin on GPIO port B pin = Pin(("GPIO_1", 21), Pin.IN) # create input pin on GPIO1
pin = Pin(("gpiob", 21), Pin.OUT, value=1) # set pin high on creation pin = Pin(("GPIO_1", 21), Pin.OUT, value=1) # set pin high on creation
pin = Pin(("gpiob", 21), Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor pin = Pin(("GPIO_1", 21), Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
switch = Pin(("gpioc", 6), Pin.IN) # create input pin for a switch switch = Pin(("GPIO_2", 6), Pin.IN) # create input pin for a switch
switch.irq(lambda t: print("SW2 changed")) # enable an interrupt when switch state is changed switch.irq(lambda t: print("SW2 changed")) # enable an interrupt when switch state is changed
Hardware I2C bus Hardware I2C bus
---------------- ----------------
@@ -63,7 +63,7 @@ Hardware I2C is accessed via the :ref:`machine.I2C <machine.I2C>` class::
from machine import I2C from machine import I2C
i2c = I2C("i2c0") # construct an i2c bus i2c = I2C("I2C_0") # construct an i2c bus
print(i2c) # print device name print(i2c) # print device name
i2c.scan() # scan the device for available I2C slaves i2c.scan() # scan the device for available I2C slaves
@@ -84,11 +84,11 @@ Hardware SPI is accessed via the :ref:`machine.SPI <machine.SPI>` class::
from machine import SPI from machine import SPI
spi = SPI("spi0") # construct a spi bus with default configuration spi = SPI("SPI_0") # construct a spi bus with default configuration
spi.init(baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB) # set configuration spi.init(baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB) # set configuration
# equivalently, construct spi bus and set configuration at the same time # equivalently, construct spi bus and set configuration at the same time
spi = SPI("spi0", baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB) spi = SPI("SPI_0", baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB)
print(spi) # print device name and bus configuration print(spi) # print device name and bus configuration
spi.read(4) # read 4 bytes on MISO spi.read(4) # read 4 bytes on MISO
@@ -146,7 +146,7 @@ Use the :ref:`zsensor.Sensor <zsensor.Sensor>` class to access sensor data::
import zsensor import zsensor
from zsensor import Sensor from zsensor import Sensor
accel = Sensor("fxos8700") # create sensor object for the accelerometer accel = Sensor("FXOX8700") # create sensor object for the accelerometer
accel.measure() # obtain a measurement reading from the accelerometer accel.measure() # obtain a measurement reading from the accelerometer

View File

@@ -31,8 +31,8 @@ With your serial program open (PuTTY, screen, picocom, etc) you may see a
blank screen with a flashing cursor. Press Enter (or reset the board) and blank screen with a flashing cursor. Press Enter (or reset the board) and
you should be presented with the following text:: you should be presented with the following text::
*** Booting Zephyr OS build v3.7.0 *** *** Booting Zephyr OS build zephyr-v3.1.0 ***
MicroPython v1.24.0-preview.179.g5b85b24bd on 2024-08-05; zephyr-frdm_k64f with mk64f12 MicroPython v1.19.1-9-g4fd54a475 on 2022-06-17; zephyr-frdm_k64f with mk64f12
Type "help()" for more information. Type "help()" for more information.
>>> >>>

View File

@@ -44,36 +44,28 @@ int mp_soft_spi_ioctl(void *self_in, uint32_t cmd) {
return 0; return 0;
} }
static uint8_t swap_bits(uint8_t byte) {
const static uint8_t swap_table[16] = {
0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f
};
return ((swap_table[byte & 0x0f] << 4) | swap_table[byte >> 4]);
}
void mp_soft_spi_transfer(void *self_in, size_t len, const uint8_t *src, uint8_t *dest) { void mp_soft_spi_transfer(void *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
mp_soft_spi_obj_t *self = (mp_soft_spi_obj_t*)self_in; mp_soft_spi_obj_t *self = (mp_soft_spi_obj_t*)self_in;
uint32_t delay_half = self->delay_half; uint32_t delay_half = self->delay_half;
// only MSB transfer is implemented
// If a port defines MICROPY_HW_SOFTSPI_MIN_DELAY, and the configured // If a port defines MICROPY_HW_SOFTSPI_MIN_DELAY, and the configured
// delay_half is equal to this value, then the software SPI implementation // delay_half is equal to this value, then the software SPI implementation
// will run as fast as possible, limited only by CPU speed and GPIO time. // will run as fast as possible, limited only by CPU speed and GPIO time.
#ifdef MICROPY_HW_SOFTSPI_MIN_DELAY #ifdef MICROPY_HW_SOFTSPI_MIN_DELAY
if (delay_half == MICROPY_HW_SOFTSPI_MIN_DELAY) { if (delay_half == MICROPY_HW_SOFTSPI_MIN_DELAY) {
for (size_t i = 0; i < len; ++i) { for (size_t i = 0; i < len; ++i) {
uint8_t data_out = self->firstbit != MICROPY_PY_MACHINE_SPI_MSB ? uint8_t data_out = src[i];
src[i] : swap_bits(src[i]);
uint8_t data_in = 0; uint8_t data_in = 0;
for (int j = 0; j < 8; ++j, data_out >>= 1) { for (int j = 0; j < 8; ++j, data_out <<= 1) {
mp_hal_pin_write(self->mosi, data_out & 1); mp_hal_pin_write(self->mosi, (data_out >> 7) & 1);
mp_hal_pin_write(self->sck, 1 - self->polarity); mp_hal_pin_write(self->sck, 1 - self->polarity);
data_in = (data_in << 1) | mp_hal_pin_read(self->miso); data_in = (data_in << 1) | mp_hal_pin_read(self->miso);
mp_hal_pin_write(self->sck, self->polarity); mp_hal_pin_write(self->sck, self->polarity);
} }
if (dest != NULL) { if (dest != NULL) {
dest[i] = self->firstbit == MICROPY_PY_MACHINE_SPI_MSB ? dest[i] = data_in;
data_in : swap_bits(data_in);
} }
} }
return; return;
@@ -81,11 +73,10 @@ void mp_soft_spi_transfer(void *self_in, size_t len, const uint8_t *src, uint8_t
#endif #endif
for (size_t i = 0; i < len; ++i) { for (size_t i = 0; i < len; ++i) {
uint8_t data_out = self->firstbit != MICROPY_PY_MACHINE_SPI_MSB ? uint8_t data_out = src[i];
src[i] : swap_bits(src[i]);
uint8_t data_in = 0; uint8_t data_in = 0;
for (int j = 0; j < 8; ++j, data_out >>= 1) { for (int j = 0; j < 8; ++j, data_out <<= 1) {
mp_hal_pin_write(self->mosi, data_out & 1); mp_hal_pin_write(self->mosi, (data_out >> 7) & 1);
if (self->phase == 0) { if (self->phase == 0) {
mp_hal_delay_us_fast(delay_half); mp_hal_delay_us_fast(delay_half);
mp_hal_pin_write(self->sck, 1 - self->polarity); mp_hal_pin_write(self->sck, 1 - self->polarity);
@@ -103,8 +94,7 @@ void mp_soft_spi_transfer(void *self_in, size_t len, const uint8_t *src, uint8_t
} }
} }
if (dest != NULL) { if (dest != NULL) {
dest[i] = self->firstbit == MICROPY_PY_MACHINE_SPI_MSB ? dest[i] = data_in;
data_in : swap_bits(data_in);
} }
} }
} }

View File

@@ -42,7 +42,6 @@ typedef struct _mp_soft_spi_obj_t {
uint32_t delay_half; // microsecond delay for half SCK period uint32_t delay_half; // microsecond delay for half SCK period
uint8_t polarity; uint8_t polarity;
uint8_t phase; uint8_t phase;
uint8_t firstbit;
mp_hal_pin_obj_t sck; mp_hal_pin_obj_t sck;
mp_hal_pin_obj_t mosi; mp_hal_pin_obj_t mosi;
mp_hal_pin_obj_t miso; mp_hal_pin_obj_t miso;

View File

@@ -95,7 +95,7 @@ typedef enum {
// AP mode commands. // AP mode commands.
NINA_CMD_START_AP_OPEN = 0x18, NINA_CMD_START_AP_OPEN = 0x18,
NINA_CMD_START_AP_WPA = 0x19, NINA_CMD_START_AP_WEP = 0x19,
// AP mode scan commands. // AP mode scan commands.
NINA_CMD_AP_START_SCAN = 0x36, NINA_CMD_AP_START_SCAN = 0x36,
@@ -395,7 +395,7 @@ int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t
uint8_t status = NINA_STATUS_AP_FAILED; uint8_t status = NINA_STATUS_AP_FAILED;
if ((key == NULL && security != NINA_SEC_OPEN) || if ((key == NULL && security != NINA_SEC_OPEN) ||
(security != NINA_SEC_OPEN && security != NINA_SEC_WPA_PSK)) { (security != NINA_SEC_OPEN && security != NINA_SEC_WEP)) {
return -1; return -1;
} }
@@ -406,8 +406,8 @@ int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t
return -1; return -1;
} }
break; break;
case NINA_SEC_WPA_PSK: case NINA_SEC_WEP:
if (nina_send_command_read_ack(NINA_CMD_START_AP_WPA, if (nina_send_command_read_ack(NINA_CMD_START_AP_WEP,
3, ARG_8BITS, NINA_ARGS(ARG_STR(ssid), ARG_STR(key), ARG_BYTE(channel))) != SPI_ACK) { 3, ARG_8BITS, NINA_ARGS(ARG_STR(ssid), ARG_STR(key), ARG_BYTE(channel))) != SPI_ACK) {
return -1; return -1;
} }

View File

@@ -1,12 +1,12 @@
# Dynamic Native Modules # Dynamic Native Modules
Dynamic Native Modules are .mpy files that contain native machine code from a Dynamic Native Modules are .mpy files that contain native machine code from a
language other than Python. For more info see [the language other than Python. For more info see [the documentation]
documentation](https://docs.micropython.org/en/latest/develop/natmod.html). (https://docs.micropython.org/en/latest/develop/natmod.html).
This should not be confused with [User C This should not be confused with [User C Modules]
Modules](https://docs.micropython.org/en/latest/develop/cmodules.html) which are (https://docs.micropython.org/en/latest/develop/cmodules.html) which are a
a mechanism to add additional out-of-tree modules into the firmware build. mechanism to add additional out-of-tree modules into the firmware build.
## Examples ## Examples

View File

@@ -11,7 +11,7 @@
const char *stack_top; const char *stack_top;
void mp_cstack_check(void) { void mp_stack_check(void) {
// Assumes descending stack on target // Assumes descending stack on target
volatile char dummy; volatile char dummy;
if (stack_top - &dummy >= STACK_LIMIT) { if (stack_top - &dummy >= STACK_LIMIT) {

View File

@@ -1,52 +1,27 @@
# Very simple HTTP client example:
# - Connects to a server.
# - Sends a HTTP request.
# - Reads the result.
#
# This example works in both MicroPython and CPython.
#
# To implement an HTTP client using less code, use mip to install the requests package:
# https://github.com/micropython/micropython-lib/tree/master/python-ecosys/requests
import socket import socket
# `addr_family` selects IPv4 vs IPv6: 0 means either, or use def main(use_stream=False):
# socket.AF_INET or socket.AF_INET6 to select a particular one. s = socket.socket()
def main(url, addr_family=0, use_stream=False):
# Split the given URL into components.
proto, _, host, path = url.split(b"/", 3)
assert proto == b"http:"
# Lookup the server address, for the given family and socket type. ai = socket.getaddrinfo("google.com", 80)
ai = socket.getaddrinfo(host, 80, addr_family, socket.SOCK_STREAM)
print("Address infos:", ai) print("Address infos:", ai)
addr = ai[0][-1]
# Select the first address.
ai = ai[0]
# Create a socket with the server's family, type and proto.
s = socket.socket(ai[0], ai[1], ai[2])
# Connect to the server.
addr = ai[-1]
print("Connect address:", addr) print("Connect address:", addr)
s.connect(addr) s.connect(addr)
# Send request and read response.
request = b"GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n" % (path, host)
if use_stream: if use_stream:
# MicroPython socket objects support stream (aka file) interface # MicroPython socket objects support stream (aka file) interface
# directly, but the line below is needed for CPython. # directly, but the line below is needed for CPython.
s = s.makefile("rwb", 0) s = s.makefile("rwb", 0)
s.write(request) s.write(b"GET / HTTP/1.0\r\n\r\n")
print(s.read()) print(s.read())
else: else:
s.send(request) s.send(b"GET / HTTP/1.0\r\n\r\n")
print(s.recv(4096)) print(s.recv(4096))
# Close the socket.
s.close() s.close()
main(b"http://www.google.com/") main()

View File

@@ -1,62 +1,32 @@
# Very simple HTTPS client example:
# - Connects to a server.
# - Upgrades the connection to a TLS connection.
# - Sends a HTTP request.
# - Reads the result.
#
# This example works in both MicroPython and CPython.
#
# To implement an HTTPS client using less code, use mip to install the requests package:
# https://github.com/micropython/micropython-lib/tree/master/python-ecosys/requests
import socket import socket
import ssl import ssl
# `addr_family` selects IPv4 vs IPv6: 0 means either, or use def main(use_stream=True):
# socket.AF_INET or socket.AF_INET6 to select a particular one. s = socket.socket()
def main(url, addr_family=0, use_stream=True):
# Split the given URL into components.
proto, _, host, path = url.split(b"/", 3)
assert proto == b"https:"
# Lookup the server address, for the given family and socket type. ai = socket.getaddrinfo("google.com", 443)
ai = socket.getaddrinfo(host, 443, addr_family, socket.SOCK_STREAM)
print("Address infos:", ai) print("Address infos:", ai)
addr = ai[0][-1]
# Select the first address.
ai = ai[0]
# Create a socket with the server's family, type and proto.
s = socket.socket(ai[0], ai[1], ai[2])
# Connect to the server.
addr = ai[-1]
print("Connect address:", addr) print("Connect address:", addr)
s.connect(addr) s.connect(addr)
# Upgrade the socket to a TLS connection. s = ssl.wrap_socket(s)
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
s = ctx.wrap_socket(s)
print(s) print(s)
# Send request and read response.
request = b"GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n" % (path, host)
if use_stream: if use_stream:
# Both CPython and MicroPython SSLSocket objects support read() and # Both CPython and MicroPython SSLSocket objects support read() and
# write() methods. # write() methods.
s.write(request) s.write(b"GET / HTTP/1.0\r\n\r\n")
print(s.read(4096)) print(s.read(4096))
else: else:
# MicroPython SSLSocket objects implement only stream interface, not # MicroPython SSLSocket objects implement only stream interface, not
# socket interface # socket interface
s.send(request) s.send(b"GET / HTTP/1.0\r\n\r\n")
print(s.recv(4096)) print(s.recv(4096))
# Close the socket.
s.close() s.close()
main(b"https://www.google.com/") main()

View File

@@ -37,13 +37,13 @@ def read_nonblocking(poller, sock, n):
return data return data
def main(url, addr_family=0): def main(url):
# Split the given URL into components. # Split the given URL into components.
proto, _, host, path = url.split(b"/", 3) proto, _, host, path = url.split(b"/", 3)
assert proto == b"https:" assert proto == b"https:"
# Note: this getaddrinfo() call is blocking! # Note: this getaddrinfo() call is blocking!
ai = socket.getaddrinfo(host, 443, addr_family, socket.SOCK_STREAM)[0] ai = socket.getaddrinfo(host, 443)[0]
addr = ai[-1] addr = ai[-1]
print("Connect address:", addr) print("Connect address:", addr)

View File

@@ -68,87 +68,6 @@ MP_DEFINE_CONST_OBJ_TYPE(
locals_dict, &example_Timer_locals_dict locals_dict, &example_Timer_locals_dict
); );
// What follows is a *separate* class definition that demonstrates more
// advanced techniques to implement other Python-like features, such as:
//
// - A custom representation for __repr__ and __str__.
// - Custom attribute handling to create a read/write "property".
//
// It re-uses some of the elements of the basic Timer class. This is allowed
// because they both use example_Timer_obj_t as the instance structure.
// Handles AdvancedTimer.__repr__, AdvancedTimer.__str__.
static void example_AdvancedTimer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
// Get the elapsed time. In this case, it's also a demonstration of calling
// the equivalent of self.time() in the C API. This is not usually very
// efficient, but it can sometimes be useful.
mp_uint_t elapsed = mp_obj_get_int(example_Timer_time(self_in));
// We'll make all representations print at least the class name.
mp_printf(print, "%q()", MP_QSTR_AdvancedTimer);
// Decide what else to print based on print kind.
if (kind == PRINT_STR) {
// For __str__, let's attempt to make it more readable.
mp_printf(print, " # created %d seconds ago", elapsed / 1000);
}
}
// Handles AdvancedTimer.seconds for reading and writing.
static void example_AdvancedTimer_attribute_handler(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
// In this example, we only want to handle the .seconds attribute in a
// special way.
if (attr != MP_QSTR_seconds) {
// Attribute not found, continue lookup in locals dict. This way,
// methods like .time() will be handled normally.
dest[1] = MP_OBJ_SENTINEL;
return;
}
// Get reference to AdvancedTimer instance.
example_Timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
// Check if this is a read operation.
if (dest[0] == MP_OBJ_NULL) {
// It's read, so "return" elapsed seconds by storing it in dest[0].
mp_uint_t elapsed = mp_hal_ticks_ms() - self->start_time;
dest[0] = mp_obj_new_int_from_uint(elapsed / 1000);
return;
}
// Check if this is a delete or store operation.
else if (dest[0] == MP_OBJ_SENTINEL) {
// It's delete or store. Now check which one.
if (dest[1] == MP_OBJ_NULL) {
// It's delete. But in this example we don't want to allow it
// so we just return.
return;
} else {
// It's write. First, get the value that the user is trying to set.
mp_uint_t desired_ms = mp_obj_get_int(dest[1]) * 1000;
// Use it to update the start time. This way, the next read will
// report the updated time.
self->start_time = mp_hal_ticks_ms() - desired_ms;
// Indicate successful store.
dest[0] = MP_OBJ_NULL;
return;
}
}
}
// This defines the type(AdvancedTimer) object.
MP_DEFINE_CONST_OBJ_TYPE(
example_type_AdvancedTimer,
MP_QSTR_AdvancedTimer,
MP_TYPE_FLAG_NONE,
attr, example_AdvancedTimer_attribute_handler,
print, example_AdvancedTimer_print,
make_new, example_Timer_make_new,
locals_dict, &example_Timer_locals_dict
);
// Define all attributes of the module. // Define all attributes of the module.
// Table entries are key/value pairs of the attribute name (a string) // Table entries are key/value pairs of the attribute name (a string)
// and the MicroPython object reference. // and the MicroPython object reference.
@@ -158,7 +77,6 @@ static const mp_rom_map_elem_t example_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cexample) }, { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cexample) },
{ MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) }, { MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) },
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&example_type_Timer) }, { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&example_type_Timer) },
{ MP_ROM_QSTR(MP_QSTR_AdvancedTimer), MP_ROM_PTR(&example_type_AdvancedTimer) },
}; };
static MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table); static MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table);

View File

@@ -49,7 +49,6 @@ set(MICROPY_SOURCE_EXTMOD
${MICROPY_EXTMOD_DIR}/network_cyw43.c ${MICROPY_EXTMOD_DIR}/network_cyw43.c
${MICROPY_EXTMOD_DIR}/network_lwip.c ${MICROPY_EXTMOD_DIR}/network_lwip.c
${MICROPY_EXTMOD_DIR}/network_ninaw10.c ${MICROPY_EXTMOD_DIR}/network_ninaw10.c
${MICROPY_EXTMOD_DIR}/network_ppp_lwip.c
${MICROPY_EXTMOD_DIR}/network_wiznet5k.c ${MICROPY_EXTMOD_DIR}/network_wiznet5k.c
${MICROPY_EXTMOD_DIR}/os_dupterm.c ${MICROPY_EXTMOD_DIR}/os_dupterm.c
${MICROPY_EXTMOD_DIR}/vfs.c ${MICROPY_EXTMOD_DIR}/vfs.c
@@ -276,14 +275,11 @@ if(MICROPY_PY_LWIP)
target_sources(micropy_lib_lwip INTERFACE target_sources(micropy_lib_lwip INTERFACE
${MICROPY_DIR}/shared/netutils/netutils.c ${MICROPY_DIR}/shared/netutils/netutils.c
${MICROPY_LIB_LWIP_DIR}/apps/mdns/mdns.c ${MICROPY_LIB_LWIP_DIR}/apps/mdns/mdns.c
${MICROPY_LIB_LWIP_DIR}/apps/mdns/mdns_domain.c
${MICROPY_LIB_LWIP_DIR}/apps/mdns/mdns_out.c
${MICROPY_LIB_LWIP_DIR}/core/def.c ${MICROPY_LIB_LWIP_DIR}/core/def.c
${MICROPY_LIB_LWIP_DIR}/core/dns.c ${MICROPY_LIB_LWIP_DIR}/core/dns.c
${MICROPY_LIB_LWIP_DIR}/core/inet_chksum.c ${MICROPY_LIB_LWIP_DIR}/core/inet_chksum.c
${MICROPY_LIB_LWIP_DIR}/core/init.c ${MICROPY_LIB_LWIP_DIR}/core/init.c
${MICROPY_LIB_LWIP_DIR}/core/ip.c ${MICROPY_LIB_LWIP_DIR}/core/ip.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/acd.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/autoip.c ${MICROPY_LIB_LWIP_DIR}/core/ipv4/autoip.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/dhcp.c ${MICROPY_LIB_LWIP_DIR}/core/ipv4/dhcp.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/etharp.c ${MICROPY_LIB_LWIP_DIR}/core/ipv4/etharp.c
@@ -314,32 +310,6 @@ if(MICROPY_PY_LWIP)
${MICROPY_LIB_LWIP_DIR}/core/timeouts.c ${MICROPY_LIB_LWIP_DIR}/core/timeouts.c
${MICROPY_LIB_LWIP_DIR}/core/udp.c ${MICROPY_LIB_LWIP_DIR}/core/udp.c
${MICROPY_LIB_LWIP_DIR}/netif/ethernet.c ${MICROPY_LIB_LWIP_DIR}/netif/ethernet.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/auth.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/ccp.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/chap-md5.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/chap_ms.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/chap-new.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/demand.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/eap.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/ecp.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/eui64.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/fsm.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/ipcp.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/ipv6cp.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/lcp.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/magic.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/mppe.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/multilink.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/polarssl/md5.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/pppapi.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/ppp.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/pppcrypt.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/pppoe.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/pppol2tp.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/pppos.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/upap.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/utils.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/vj.c
) )
list(APPEND MICROPY_INC_CORE list(APPEND MICROPY_INC_CORE

View File

@@ -42,7 +42,6 @@ SRC_EXTMOD_C += \
extmod/modsocket.c \ extmod/modsocket.c \
extmod/modtls_axtls.c \ extmod/modtls_axtls.c \
extmod/modtls_mbedtls.c \ extmod/modtls_mbedtls.c \
extmod/mbedtls/mbedtls_alt.c \
extmod/modtime.c \ extmod/modtime.c \
extmod/moductypes.c \ extmod/moductypes.c \
extmod/modvfs.c \ extmod/modvfs.c \
@@ -52,7 +51,6 @@ SRC_EXTMOD_C += \
extmod/network_esp_hosted.c \ extmod/network_esp_hosted.c \
extmod/network_lwip.c \ extmod/network_lwip.c \
extmod/network_ninaw10.c \ extmod/network_ninaw10.c \
extmod/network_ppp_lwip.c \
extmod/network_wiznet5k.c \ extmod/network_wiznet5k.c \
extmod/os_dupterm.c \ extmod/os_dupterm.c \
extmod/vfs.c \ extmod/vfs.c \
@@ -169,7 +167,6 @@ SRC_LIB_LIBM_DBL_SQRT_HW_C += lib/libm_dbl/thumb_vfp_sqrt.c
# Too many warnings in libm_dbl, disable for now. # Too many warnings in libm_dbl, disable for now.
$(BUILD)/lib/libm_dbl/%.o: CFLAGS += -Wno-double-promotion -Wno-float-conversion $(BUILD)/lib/libm_dbl/%.o: CFLAGS += -Wno-double-promotion -Wno-float-conversion
$(BUILD)/lib/libm_dbl/__rem_pio2_large.o: CFLAGS += -Wno-maybe-uninitialized
################################################################################ ################################################################################
# VFS FAT FS # VFS FAT FS
@@ -243,10 +240,6 @@ MBEDTLS_CONFIG_FILE ?= \"mbedtls/mbedtls_config_port.h\"
GIT_SUBMODULES += $(MBEDTLS_DIR) GIT_SUBMODULES += $(MBEDTLS_DIR)
CFLAGS_EXTMOD += -DMBEDTLS_CONFIG_FILE=$(MBEDTLS_CONFIG_FILE) CFLAGS_EXTMOD += -DMBEDTLS_CONFIG_FILE=$(MBEDTLS_CONFIG_FILE)
CFLAGS_EXTMOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include CFLAGS_EXTMOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include
ifeq ($(MICROPY_PY_SSL_ECDSA_SIGN_ALT),1)
CFLAGS_EXTMOD += -DMICROPY_PY_SSL_ECDSA_SIGN_ALT=1
LDFLAGS_EXTMOD += -Wl,--wrap=mbedtls_ecdsa_write_signature
endif
SRC_THIRDPARTY_C += lib/mbedtls_errors/mp_mbedtls_errors.c SRC_THIRDPARTY_C += lib/mbedtls_errors/mp_mbedtls_errors.c
SRC_THIRDPARTY_C += $(addprefix $(MBEDTLS_DIR)/library/,\ SRC_THIRDPARTY_C += $(addprefix $(MBEDTLS_DIR)/library/,\
aes.c \ aes.c \
@@ -338,8 +331,6 @@ $(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS += -Wno-address
SRC_THIRDPARTY_C += shared/netutils/netutils.c SRC_THIRDPARTY_C += shared/netutils/netutils.c
SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\ SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\
apps/mdns/mdns.c \ apps/mdns/mdns.c \
apps/mdns/mdns_domain.c \
apps/mdns/mdns_out.c \
core/def.c \ core/def.c \
core/dns.c \ core/dns.c \
core/inet_chksum.c \ core/inet_chksum.c \
@@ -357,7 +348,6 @@ SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\
core/tcp_out.c \ core/tcp_out.c \
core/timeouts.c \ core/timeouts.c \
core/udp.c \ core/udp.c \
core/ipv4/acd.c \
core/ipv4/autoip.c \ core/ipv4/autoip.c \
core/ipv4/dhcp.c \ core/ipv4/dhcp.c \
core/ipv4/etharp.c \ core/ipv4/etharp.c \
@@ -376,32 +366,6 @@ SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\
core/ipv6/mld6.c \ core/ipv6/mld6.c \
core/ipv6/nd6.c \ core/ipv6/nd6.c \
netif/ethernet.c \ netif/ethernet.c \
netif/ppp/auth.c \
netif/ppp/ccp.c \
netif/ppp/chap-md5.c \
netif/ppp/chap_ms.c \
netif/ppp/chap-new.c \
netif/ppp/demand.c \
netif/ppp/eap.c \
netif/ppp/ecp.c \
netif/ppp/eui64.c \
netif/ppp/fsm.c \
netif/ppp/ipcp.c \
netif/ppp/ipv6cp.c \
netif/ppp/lcp.c \
netif/ppp/magic.c \
netif/ppp/mppe.c \
netif/ppp/multilink.c \
netif/ppp/polarssl/md5.c \
netif/ppp/pppapi.c \
netif/ppp/ppp.c \
netif/ppp/pppcrypt.c \
netif/ppp/pppoe.c \
netif/ppp/pppol2tp.c \
netif/ppp/pppos.c \
netif/ppp/upap.c \
netif/ppp/utils.c \
netif/ppp/vj.c \
) )
ifeq ($(MICROPY_PY_LWIP_LOOPBACK),1) ifeq ($(MICROPY_PY_LWIP_LOOPBACK),1)
CFLAGS_EXTMOD += -DLWIP_NETIF_LOOPBACK=1 CFLAGS_EXTMOD += -DLWIP_NETIF_LOOPBACK=1
@@ -562,7 +526,6 @@ ifeq ($(MICROPY_PY_OPENAMP),1)
OPENAMP_DIR = lib/open-amp OPENAMP_DIR = lib/open-amp
LIBMETAL_DIR = lib/libmetal LIBMETAL_DIR = lib/libmetal
GIT_SUBMODULES += $(LIBMETAL_DIR) $(OPENAMP_DIR) GIT_SUBMODULES += $(LIBMETAL_DIR) $(OPENAMP_DIR)
MICROPY_PY_OPENAMP_MODE ?= 0
include $(TOP)/extmod/libmetal/libmetal.mk include $(TOP)/extmod/libmetal/libmetal.mk
INC += -I$(TOP)/$(OPENAMP_DIR) INC += -I$(TOP)/$(OPENAMP_DIR)
@@ -572,21 +535,12 @@ ifeq ($(MICROPY_PY_OPENAMP_REMOTEPROC),1)
CFLAGS += -DMICROPY_PY_OPENAMP_REMOTEPROC=1 CFLAGS += -DMICROPY_PY_OPENAMP_REMOTEPROC=1
endif endif
ifeq ($(MICROPY_PY_OPENAMP_MODE),0)
CFLAGS += -DMICROPY_PY_OPENAMP_HOST=1
CFLAGS_THIRDPARTY += -DVIRTIO_DRIVER_ONLY
else ifeq ($(MICROPY_PY_OPENAMP_MODE),1)
CFLAGS += -DMICROPY_PY_OPENAMP_DEVICE=1
CFLAGS_THIRDPARTY += -DVIRTIO_DEVICE_ONLY
else
$(error Invalid Open-AMP mode specified: $(MICROPY_PY_OPENAMP_MODE))
endif
CFLAGS_THIRDPARTY += \ CFLAGS_THIRDPARTY += \
-I$(BUILD)/openamp \ -I$(BUILD)/openamp \
-I$(TOP)/$(OPENAMP_DIR) \ -I$(TOP)/$(OPENAMP_DIR) \
-I$(TOP)/$(OPENAMP_DIR)/lib/include/ \ -I$(TOP)/$(OPENAMP_DIR)/lib/include/ \
-DMETAL_INTERNAL \ -DMETAL_INTERNAL \
-DVIRTIO_DRIVER_ONLY \
-DNO_ATOMIC_64_SUPPORT \ -DNO_ATOMIC_64_SUPPORT \
-DRPMSG_BUFFER_SIZE=512 \ -DRPMSG_BUFFER_SIZE=512 \

View File

@@ -4,13 +4,13 @@
# This replicates the basic functionality of the pre-processor, including adding a "micropython" # This replicates the basic functionality of the pre-processor, including adding a "micropython"
# platform that is almost identical to the built-in "generic" platform with a few small changes # platform that is almost identical to the built-in "generic" platform with a few small changes
# provided by the files in extmod/libmetal. # provided by the files in extmod/libmetal.
$(BUILD)/openamp: | $(BUILD) $(BUILD)/openamp: $(BUILD)
$(MKDIR) -p $@ $(MKDIR) -p $@
$(BUILD)/openamp/metal: | $(BUILD)/openamp $(BUILD)/openamp/metal: $(BUILD)/openamp
$(MKDIR) -p $@ $(MKDIR) -p $@
$(BUILD)/openamp/metal/config.h: $(TOP)/$(LIBMETAL_DIR)/lib/config.h | $(BUILD)/openamp/metal $(BUILD)/openamp/metal/config.h: $(BUILD)/openamp/metal $(TOP)/$(LIBMETAL_DIR)/lib/config.h
@$(ECHO) "GEN $@" @$(ECHO) "GEN $@"
@for file in $(TOP)/$(LIBMETAL_DIR)/lib/*.c $(TOP)/$(LIBMETAL_DIR)/lib/*.h; do $(SED) -e "s/@PROJECT_SYSTEM@/micropython/g" -e "s/@PROJECT_PROCESSOR@/arm/g" $$file > $(BUILD)/openamp/metal/$$(basename $$file); done @for file in $(TOP)/$(LIBMETAL_DIR)/lib/*.c $(TOP)/$(LIBMETAL_DIR)/lib/*.h; do $(SED) -e "s/@PROJECT_SYSTEM@/micropython/g" -e "s/@PROJECT_PROCESSOR@/arm/g" $$file > $(BUILD)/openamp/metal/$$(basename $$file); done
$(MKDIR) -p $(BUILD)/openamp/metal/processor/arm $(MKDIR) -p $(BUILD)/openamp/metal/processor/arm
@@ -33,6 +33,7 @@ SRC_LIBMETAL_C := $(addprefix $(BUILD)/openamp/metal/,\
shmem.c \ shmem.c \
softirq.c \ softirq.c \
version.c \ version.c \
device.c \
system/micropython/condition.c \ system/micropython/condition.c \
system/micropython/device.c \ system/micropython/device.c \
system/micropython/io.c \ system/micropython/io.c \

View File

@@ -33,6 +33,12 @@
#include "extmod/modmachine.h" #include "extmod/modmachine.h"
// if a port didn't define MSB/LSB constants then provide them
#ifndef MICROPY_PY_MACHINE_SPI_MSB
#define MICROPY_PY_MACHINE_SPI_MSB (0)
#define MICROPY_PY_MACHINE_SPI_LSB (1)
#endif
/******************************************************************************/ /******************************************************************************/
// MicroPython bindings for generic machine.SPI // MicroPython bindings for generic machine.SPI
@@ -148,9 +154,9 @@ static uint32_t baudrate_to_delay_half(uint32_t baudrate) {
static void mp_machine_soft_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { static void mp_machine_soft_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "SoftSPI(baudrate=%u, polarity=%u, phase=%u, firstbit=%u," mp_printf(print, "SoftSPI(baudrate=%u, polarity=%u, phase=%u,"
" sck=" MP_HAL_PIN_FMT ", mosi=" MP_HAL_PIN_FMT ", miso=" MP_HAL_PIN_FMT ")", " sck=" MP_HAL_PIN_FMT ", mosi=" MP_HAL_PIN_FMT ", miso=" MP_HAL_PIN_FMT ")",
baudrate_from_delay_half(self->spi.delay_half), self->spi.polarity, self->spi.phase, self->spi.firstbit, baudrate_from_delay_half(self->spi.delay_half), self->spi.polarity, self->spi.phase,
mp_hal_pin_name(self->spi.sck), mp_hal_pin_name(self->spi.mosi), mp_hal_pin_name(self->spi.miso)); mp_hal_pin_name(self->spi.sck), mp_hal_pin_name(self->spi.mosi), mp_hal_pin_name(self->spi.miso));
} }
@@ -179,7 +185,9 @@ static mp_obj_t mp_machine_soft_spi_make_new(const mp_obj_type_t *type, size_t n
if (args[ARG_bits].u_int != 8) { if (args[ARG_bits].u_int != 8) {
mp_raise_ValueError(MP_ERROR_TEXT("bits must be 8")); mp_raise_ValueError(MP_ERROR_TEXT("bits must be 8"));
} }
self->spi.firstbit = args[ARG_firstbit].u_int; if (args[ARG_firstbit].u_int != MICROPY_PY_MACHINE_SPI_MSB) {
mp_raise_ValueError(MP_ERROR_TEXT("firstbit must be MSB"));
}
if (args[ARG_sck].u_obj == MP_OBJ_NULL if (args[ARG_sck].u_obj == MP_OBJ_NULL
|| args[ARG_mosi].u_obj == MP_OBJ_NULL || args[ARG_mosi].u_obj == MP_OBJ_NULL
|| args[ARG_miso].u_obj == MP_OBJ_NULL) { || args[ARG_miso].u_obj == MP_OBJ_NULL) {
@@ -198,12 +206,11 @@ static mp_obj_t mp_machine_soft_spi_make_new(const mp_obj_type_t *type, size_t n
static void mp_machine_soft_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static void mp_machine_soft_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t *)self_in; mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t *)self_in;
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso }; enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_sck, ARG_mosi, ARG_miso };
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
@@ -220,9 +227,6 @@ static void mp_machine_soft_spi_init(mp_obj_base_t *self_in, size_t n_args, cons
if (args[ARG_phase].u_int != -1) { if (args[ARG_phase].u_int != -1) {
self->spi.phase = args[ARG_phase].u_int; self->spi.phase = args[ARG_phase].u_int;
} }
if (args[ARG_firstbit].u_int != -1) {
self->spi.firstbit = args[ARG_firstbit].u_int;
}
if (args[ARG_sck].u_obj != MP_OBJ_NULL) { if (args[ARG_sck].u_obj != MP_OBJ_NULL) {
self->spi.sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj); self->spi.sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj);
} }

View File

@@ -157,11 +157,6 @@ static mp_obj_t usb_device_active(size_t n_args, const mp_obj_t *args) {
} }
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(usb_device_active_obj, 1, 2, usb_device_active); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(usb_device_active_obj, 1, 2, usb_device_active);
static mp_obj_t usb_remote_wakeup(mp_obj_t self) {
return mp_obj_new_bool(tud_remote_wakeup());
}
static MP_DEFINE_CONST_FUN_OBJ_1(usb_remote_wakeup_obj, usb_remote_wakeup);
static mp_obj_t usb_device_stall(size_t n_args, const mp_obj_t *args) { static mp_obj_t usb_device_stall(size_t n_args, const mp_obj_t *args) {
mp_obj_usb_device_t *self = (mp_obj_usb_device_t *)MP_OBJ_TO_PTR(args[0]); mp_obj_usb_device_t *self = (mp_obj_usb_device_t *)MP_OBJ_TO_PTR(args[0]);
int epnum = mp_obj_get_int(args[1]); int epnum = mp_obj_get_int(args[1]);
@@ -277,7 +272,6 @@ static const mp_rom_map_elem_t usb_device_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_submit_xfer), MP_ROM_PTR(&usb_device_submit_xfer_obj) }, { MP_ROM_QSTR(MP_QSTR_submit_xfer), MP_ROM_PTR(&usb_device_submit_xfer_obj) },
{ MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&usb_device_active_obj) }, { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&usb_device_active_obj) },
{ MP_ROM_QSTR(MP_QSTR_stall), MP_ROM_PTR(&usb_device_stall_obj) }, { MP_ROM_QSTR(MP_QSTR_stall), MP_ROM_PTR(&usb_device_stall_obj) },
{ MP_ROM_QSTR(MP_QSTR_remote_wakeup), MP_ROM_PTR(&usb_remote_wakeup_obj) },
// Built-in driver constants // Built-in driver constants
{ MP_ROM_QSTR(MP_QSTR_BUILTIN_NONE), MP_ROM_PTR(&mp_type_usb_device_builtin_none) }, { MP_ROM_QSTR(MP_QSTR_BUILTIN_NONE), MP_ROM_PTR(&mp_type_usb_device_builtin_none) },

View File

@@ -1,88 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright The Mbed TLS Contributors
* Copyright (c) 2024 Damien P. George
*
* This file provides default fallback functions for use with alternate
* cryptography functions implemented in Python.
*/
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
#if defined(MBEDTLS_ECP_RESTARTABLE) || defined(MBEDTLS_ECDSA_DETERMINISTIC)
#error "MICROPY_PY_SSL_ECDSA_SIGN_ALT cannot be used with MBEDTLS_ECP_RESTARTABLE or MBEDTLS_ECDSA_DETERMINISTIC"
#endif
#include <string.h>
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
#include "mbedtls/platform.h"
#include "mbedtls/ssl.h"
#include "mbedtls/error.h"
#include "mbedtls/ecdsa.h"
#include "mbedtls/asn1write.h"
extern int micropy_mbedtls_ecdsa_sign_alt(const mbedtls_mpi *d, const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t sig_size, size_t *slen);
// Compute and write signature
// See lib/mbedtls/library/ecdsa.c:688
//
// Note: To avoid duplicating a lot of code, MBEDTLS_ECDSA_SIGN_ALT is not defined,
// which allows the default mbedtls_ecdsa_sign to be used as a fallback function.
// However, mbedtls_ecdsa_sign cannot be wrapped because it is called internally
// within its object file, so we wrap mbedtls_ecdsa_read/write_signature instead.
int __wrap_mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t sig_size, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng) {
(void)md_alg;
if (f_rng == NULL) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
// Check if curve is supported for ECDSA.
if (!mbedtls_ecdsa_can_do(ctx->grp.id) || ctx->grp.N.p == NULL) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
// Try signing with the alternative function first.
int ret = micropy_mbedtls_ecdsa_sign_alt(&ctx->d, hash, hlen, sig, sig_size, slen);
// Fallback to the default mbedtls implementation if needed.
if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED) {
mbedtls_mpi r, s;
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);
size_t len = 0;
unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 };
unsigned char *p = buf + sizeof(buf);
MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ctx->grp, &r, &s, &ctx->d, hash, hlen, f_rng, p_rng));
MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_mpi(&p, buf, &s));
MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_mpi(&p, buf, &r));
MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len));
MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_tag(&p, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
if (len > sig_size) {
ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
} else {
ret = 0;
*slen = len;
memcpy(sig, p, len);
}
cleanup:
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
}
return ret;
}
#endif

View File

@@ -46,7 +46,6 @@
#define MBEDTLS_ECP_DP_SECP256K1_ENABLED #define MBEDTLS_ECP_DP_SECP256K1_ENABLED
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
#define MBEDTLS_CAN_ECDH #define MBEDTLS_CAN_ECDH
#define MBEDTLS_PK_CAN_ECDSA_SIGN #define MBEDTLS_PK_CAN_ECDSA_SIGN
#define MBEDTLS_PKCS1_V15 #define MBEDTLS_PKCS1_V15
@@ -73,7 +72,6 @@
#define MBEDTLS_ECP_C #define MBEDTLS_ECP_C
#define MBEDTLS_ENTROPY_C #define MBEDTLS_ENTROPY_C
#define MBEDTLS_ERROR_C #define MBEDTLS_ERROR_C
#define MBEDTLS_GCM_C
#define MBEDTLS_MD_C #define MBEDTLS_MD_C
#define MBEDTLS_MD5_C #define MBEDTLS_MD5_C
#define MBEDTLS_OID_C #define MBEDTLS_OID_C

View File

@@ -53,9 +53,6 @@ typedef struct _mp_obj_task_t {
typedef struct _mp_obj_task_queue_t { typedef struct _mp_obj_task_queue_t {
mp_obj_base_t base; mp_obj_base_t base;
mp_obj_task_t *heap; mp_obj_task_t *heap;
#if MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK
mp_obj_t push_callback;
#endif
} mp_obj_task_queue_t; } mp_obj_task_queue_t;
static const mp_obj_type_t task_queue_type; static const mp_obj_type_t task_queue_type;
@@ -89,16 +86,9 @@ static int task_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) {
static mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { static mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
(void)args; (void)args;
mp_arg_check_num(n_args, n_kw, 0, MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK ? 1 : 0, false); mp_arg_check_num(n_args, n_kw, 0, 0, false);
mp_obj_task_queue_t *self = mp_obj_malloc(mp_obj_task_queue_t, type); mp_obj_task_queue_t *self = mp_obj_malloc(mp_obj_task_queue_t, type);
self->heap = (mp_obj_task_t *)mp_pairheap_new(task_lt); self->heap = (mp_obj_task_t *)mp_pairheap_new(task_lt);
#if MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK
if (n_args == 1) {
self->push_callback = args[0];
} else {
self->push_callback = MP_OBJ_NULL;
}
#endif
return MP_OBJ_FROM_PTR(self); return MP_OBJ_FROM_PTR(self);
} }
@@ -123,11 +113,6 @@ static mp_obj_t task_queue_push(size_t n_args, const mp_obj_t *args) {
task->ph_key = args[2]; task->ph_key = args[2];
} }
self->heap = (mp_obj_task_t *)mp_pairheap_push(task_lt, TASK_PAIRHEAP(self->heap), TASK_PAIRHEAP(task)); self->heap = (mp_obj_task_t *)mp_pairheap_push(task_lt, TASK_PAIRHEAP(self->heap), TASK_PAIRHEAP(task));
#if MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK
if (self->push_callback != MP_OBJ_NULL) {
mp_call_function_1(self->push_callback, MP_OBJ_NEW_SMALL_INT(0));
}
#endif
return mp_const_none; return mp_const_none;
} }
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(task_queue_push_obj, 2, 3, task_queue_push); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(task_queue_push_obj, 2, 3, task_queue_push);

View File

@@ -89,12 +89,6 @@ void __dbpanic(DB *db) {
mp_printf(&mp_plat_print, "__dbpanic(%p)\n", db); mp_printf(&mp_plat_print, "__dbpanic(%p)\n", db);
} }
static void check_btree_is_open(mp_obj_btree_t *self) {
if (!self->db) {
mp_raise_ValueError(MP_ERROR_TEXT("database closed"));
}
}
static mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) { static mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) {
mp_obj_btree_t *o = mp_obj_malloc(mp_obj_btree_t, (mp_obj_type_t *)&btree_type); mp_obj_btree_t *o = mp_obj_malloc(mp_obj_btree_t, (mp_obj_type_t *)&btree_type);
o->stream = stream; o->stream = stream;
@@ -120,28 +114,19 @@ static void btree_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind
static mp_obj_t btree_flush(mp_obj_t self_in) { static mp_obj_t btree_flush(mp_obj_t self_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
check_btree_is_open(self);
return MP_OBJ_NEW_SMALL_INT(__bt_sync(self->db, 0)); return MP_OBJ_NEW_SMALL_INT(__bt_sync(self->db, 0));
} }
static MP_DEFINE_CONST_FUN_OBJ_1(btree_flush_obj, btree_flush); static MP_DEFINE_CONST_FUN_OBJ_1(btree_flush_obj, btree_flush);
static mp_obj_t btree_close(mp_obj_t self_in) { static mp_obj_t btree_close(mp_obj_t self_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
int res; return MP_OBJ_NEW_SMALL_INT(__bt_close(self->db));
if (self->db) {
res = __bt_close(self->db);
self->db = NULL;
} else {
res = RET_SUCCESS; // Closing an already-closed DB always succeeds.
}
return MP_OBJ_NEW_SMALL_INT(res);
} }
static MP_DEFINE_CONST_FUN_OBJ_1(btree_close_obj, btree_close); static MP_DEFINE_CONST_FUN_OBJ_1(btree_close_obj, btree_close);
static mp_obj_t btree_put(size_t n_args, const mp_obj_t *args) { static mp_obj_t btree_put(size_t n_args, const mp_obj_t *args) {
(void)n_args; (void)n_args;
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
check_btree_is_open(self);
DBT key, val; DBT key, val;
buf_to_dbt(args[1], &key); buf_to_dbt(args[1], &key);
buf_to_dbt(args[2], &val); buf_to_dbt(args[2], &val);
@@ -151,7 +136,6 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put);
static mp_obj_t btree_get(size_t n_args, const mp_obj_t *args) { static mp_obj_t btree_get(size_t n_args, const mp_obj_t *args) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
check_btree_is_open(self);
DBT key, val; DBT key, val;
buf_to_dbt(args[1], &key); buf_to_dbt(args[1], &key);
int res = __bt_get(self->db, &key, &val, 0); int res = __bt_get(self->db, &key, &val, 0);
@@ -169,7 +153,6 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_get_obj, 2, 3, btree_get);
static mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) { static mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
check_btree_is_open(self);
int flags = MP_OBJ_SMALL_INT_VALUE(args[1]); int flags = MP_OBJ_SMALL_INT_VALUE(args[1]);
DBT key, val; DBT key, val;
if (n_args > 2) { if (n_args > 2) {
@@ -242,7 +225,6 @@ static mp_obj_t btree_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
static mp_obj_t btree_iternext(mp_obj_t self_in) { static mp_obj_t btree_iternext(mp_obj_t self_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
check_btree_is_open(self);
DBT key, val; DBT key, val;
int res; int res;
bool desc = self->flags & FLAG_DESC; bool desc = self->flags & FLAG_DESC;
@@ -299,7 +281,6 @@ static mp_obj_t btree_iternext(mp_obj_t self_in) {
static mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { static mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
check_btree_is_open(self);
if (value == MP_OBJ_NULL) { if (value == MP_OBJ_NULL) {
// delete // delete
DBT key; DBT key;
@@ -333,7 +314,6 @@ static mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
static mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { static mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in); mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in);
check_btree_is_open(self);
switch (op) { switch (op) {
case MP_BINARY_OP_CONTAINS: { case MP_BINARY_OP_CONTAINS: {
DBT key, val; DBT key, val;

View File

@@ -282,29 +282,23 @@ static mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size
mp_raise_ValueError(NULL); mp_raise_ValueError(NULL);
} }
size_t bpp = 1;
size_t height_required = height; size_t height_required = height;
size_t width_required = width; size_t bpp = 1;
size_t strides_required = height - 1;
switch (format) { switch (format) {
case FRAMEBUF_MVLSB: case FRAMEBUF_MVLSB:
height_required = (height + 7) & ~7; height_required = (height + 7) & ~7;
strides_required = height_required - 8;
break; break;
case FRAMEBUF_MHLSB: case FRAMEBUF_MHLSB:
case FRAMEBUF_MHMSB: case FRAMEBUF_MHMSB:
stride = (stride + 7) & ~7; stride = (stride + 7) & ~7;
width_required = (width + 7) & ~7;
break; break;
case FRAMEBUF_GS2_HMSB: case FRAMEBUF_GS2_HMSB:
stride = (stride + 3) & ~3; stride = (stride + 3) & ~3;
width_required = (width + 3) & ~3;
bpp = 2; bpp = 2;
break; break;
case FRAMEBUF_GS4_HMSB: case FRAMEBUF_GS4_HMSB:
stride = (stride + 1) & ~1; stride = (stride + 1) & ~1;
width_required = (width + 1) & ~1;
bpp = 4; bpp = 4;
break; break;
case FRAMEBUF_GS8: case FRAMEBUF_GS8:
@@ -320,7 +314,7 @@ static mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE); mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE);
if ((strides_required * stride + (height_required - strides_required) * width_required) * bpp / 8 > bufinfo.len) { if (height_required * stride * bpp / 8 > bufinfo.len) {
mp_raise_ValueError(NULL); mp_raise_ValueError(NULL);
} }
@@ -536,10 +530,6 @@ static mp_obj_t framebuf_ellipse(size_t n_args, const mp_obj_t *args_in) {
} else { } else {
mask |= ELLIPSE_MASK_ALL; mask |= ELLIPSE_MASK_ALL;
} }
if (args[2] == 0 && args[3] == 0) {
setpixel_checked(self, args[0], args[1], args[4], mask & ELLIPSE_MASK_ALL);
return mp_const_none;
}
mp_int_t two_asquare = 2 * args[2] * args[2]; mp_int_t two_asquare = 2 * args[2] * args[2];
mp_int_t two_bsquare = 2 * args[3] * args[3]; mp_int_t two_bsquare = 2 * args[3] * args[3];
mp_int_t x = args[2]; mp_int_t x = args[2];

View File

@@ -127,15 +127,15 @@ sio_fd_t sio_open(u8_t dvnum) {
} }
void sio_send(u8_t c, sio_fd_t fd) { void sio_send(u8_t c, sio_fd_t fd) {
const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(lwip_slip_stream)); mp_obj_type_t *type = mp_obj_get_type(MP_STATE_VM(lwip_slip_stream));
int error; int error;
stream_p->write(MP_STATE_VM(lwip_slip_stream), &c, 1, &error); type->stream_p->write(MP_STATE_VM(lwip_slip_stream), &c, 1, &error);
} }
u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len) { u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len) {
const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(lwip_slip_stream)); mp_obj_type_t *type = mp_obj_get_type(MP_STATE_VM(lwip_slip_stream));
int error; int error;
mp_uint_t out_sz = stream_p->read(MP_STATE_VM(lwip_slip_stream), data, len, &error); mp_uint_t out_sz = type->stream_p->read(MP_STATE_VM(lwip_slip_stream), data, len, &error);
if (out_sz == MP_STREAM_ERROR) { if (out_sz == MP_STREAM_ERROR) {
if (mp_is_nonblocking_error(error)) { if (mp_is_nonblocking_error(error)) {
return 0; return 0;
@@ -326,10 +326,6 @@ typedef struct _lwip_socket_obj_t {
int8_t state; int8_t state;
} lwip_socket_obj_t; } lwip_socket_obj_t;
static inline bool socket_is_timedout(lwip_socket_obj_t *socket, mp_uint_t ticks_start) {
return socket->timeout != -1 && (mp_uint_t)(mp_hal_ticks_ms() - ticks_start) >= socket->timeout;
}
static inline void poll_sockets(void) { static inline void poll_sockets(void) {
mp_event_wait_ms(1); mp_event_wait_ms(1);
} }
@@ -373,7 +369,7 @@ mp_obj_t lwip_format_inet_addr(const ip_addr_t *ip, mp_uint_t port) {
char ipstr[IPADDR_STRLEN_MAX]; char ipstr[IPADDR_STRLEN_MAX];
ipaddr_ntoa_r(ip, ipstr, sizeof(ipstr)); ipaddr_ntoa_r(ip, ipstr, sizeof(ipstr));
mp_obj_t tuple[2] = { mp_obj_t tuple[2] = {
tuple[0] = mp_obj_new_str_from_cstr(ipstr), tuple[0] = mp_obj_new_str(ipstr, strlen(ipstr)),
tuple[1] = mp_obj_new_int(port), tuple[1] = mp_obj_new_int(port),
}; };
return mp_obj_new_tuple(2, tuple); return mp_obj_new_tuple(2, tuple);
@@ -1040,22 +1036,26 @@ static mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
// accept incoming connection // accept incoming connection
struct tcp_pcb *volatile *incoming_connection = &lwip_socket_incoming_array(socket)[socket->incoming.connection.iget]; struct tcp_pcb *volatile *incoming_connection = &lwip_socket_incoming_array(socket)[socket->incoming.connection.iget];
if (*incoming_connection == NULL) { if (*incoming_connection == NULL) {
mp_uint_t ticks_start = mp_hal_ticks_ms(); if (socket->timeout == 0) {
for (;;) {
MICROPY_PY_LWIP_EXIT MICROPY_PY_LWIP_EXIT
poll_sockets(); m_del_obj(lwip_socket_obj_t, socket2);
MICROPY_PY_LWIP_REENTER mp_raise_OSError(MP_EAGAIN);
if (*incoming_connection != NULL) { } else if (socket->timeout != -1) {
break; mp_uint_t retries = socket->timeout / 100;
} while (*incoming_connection == NULL) {
if (socket_is_timedout(socket, ticks_start)) {
MICROPY_PY_LWIP_EXIT MICROPY_PY_LWIP_EXIT
m_del_obj(lwip_socket_obj_t, socket2); if (retries-- == 0) {
if (socket->timeout == 0) { m_del_obj(lwip_socket_obj_t, socket2);
mp_raise_OSError(MP_EAGAIN);
} else {
mp_raise_OSError(MP_ETIMEDOUT); mp_raise_OSError(MP_ETIMEDOUT);
} }
mp_hal_delay_ms(100);
MICROPY_PY_LWIP_REENTER
}
} else {
while (*incoming_connection == NULL) {
MICROPY_PY_LWIP_EXIT
poll_sockets();
MICROPY_PY_LWIP_REENTER
} }
} }
} }
@@ -1130,21 +1130,21 @@ static mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
MICROPY_PY_LWIP_EXIT MICROPY_PY_LWIP_EXIT
// And now we wait... // And now we wait...
mp_uint_t ticks_start = mp_hal_ticks_ms(); if (socket->timeout != -1) {
for (;;) { for (mp_uint_t retries = socket->timeout / 100; retries--;) {
poll_sockets(); mp_hal_delay_ms(100);
if (socket->state != STATE_CONNECTING) { if (socket->state != STATE_CONNECTING) {
break; break;
}
if (socket_is_timedout(socket, ticks_start)) {
if (socket->timeout == 0) {
mp_raise_OSError(MP_EINPROGRESS);
} else {
mp_raise_OSError(MP_ETIMEDOUT);
} }
} }
if (socket->state == STATE_CONNECTING) {
mp_raise_OSError(MP_EINPROGRESS);
}
} else {
while (socket->state == STATE_CONNECTING) {
poll_sockets();
}
} }
if (socket->state == STATE_CONNECTED) { if (socket->state == STATE_CONNECTED) {
err = ERR_OK; err = ERR_OK;
} else { } else {
@@ -1432,7 +1432,7 @@ static mp_obj_t lwip_socket_setsockopt(size_t n_args, const mp_obj_t *args) {
case IP_DROP_MEMBERSHIP: { case IP_DROP_MEMBERSHIP: {
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
if (bufinfo.len != sizeof(MP_IGMP_IP_ADDR_TYPE) * 2) { if (bufinfo.len != sizeof(ip_addr_t) * 2) {
mp_raise_ValueError(NULL); mp_raise_ValueError(NULL);
} }

View File

@@ -24,7 +24,6 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include "py/builtin.h"
#include "py/runtime.h" #include "py/runtime.h"
#if MICROPY_PY_MACHINE #if MICROPY_PY_MACHINE
@@ -36,10 +35,6 @@
#include "drivers/dht/dht.h" #include "drivers/dht/dht.h"
#endif #endif
#if !MICROPY_PY_SYS_EXIT
#error MICROPY_PY_MACHINE requires MICROPY_PY_SYS_EXIT
#endif
// The port must provide implementations of these low-level machine functions. // The port must provide implementations of these low-level machine functions.
static void mp_machine_idle(void); static void mp_machine_idle(void);
@@ -66,6 +61,12 @@ NORETURN static void mp_machine_deepsleep(size_t n_args, const mp_obj_t *args);
#include MICROPY_PY_MACHINE_INCLUDEFILE #include MICROPY_PY_MACHINE_INCLUDEFILE
#endif #endif
static mp_obj_t machine_soft_reset(void) {
pyexec_system_exit = PYEXEC_FORCED_EXIT;
mp_raise_type(&mp_type_SystemExit);
}
static MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset);
#if MICROPY_PY_MACHINE_BOOTLOADER #if MICROPY_PY_MACHINE_BOOTLOADER
NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
mp_machine_bootloader(n_args, args); mp_machine_bootloader(n_args, args);
@@ -108,7 +109,7 @@ static mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
return mp_const_none; return mp_const_none;
} }
} }
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, MICROPY_PY_MACHINE_FREQ_NUM_ARGS_MAX, machine_freq); MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq);
static mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) { static mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) {
mp_machine_lightsleep(n_args, args); mp_machine_lightsleep(n_args, args);
@@ -156,7 +157,7 @@ static const mp_rom_map_elem_t machine_module_globals_table[] = {
#endif #endif
// Reset related functions. // Reset related functions.
{ MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&mp_sys_exit_obj) }, { MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) },
#if MICROPY_PY_MACHINE_BOOTLOADER #if MICROPY_PY_MACHINE_BOOTLOADER
{ MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) }, { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) },
#endif #endif

View File

@@ -127,7 +127,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_network_country_obj, 0, 1, network_count
mp_obj_t mod_network_hostname(size_t n_args, const mp_obj_t *args) { mp_obj_t mod_network_hostname(size_t n_args, const mp_obj_t *args) {
if (n_args == 0) { if (n_args == 0) {
return mp_obj_new_str_from_cstr(mod_network_hostname_data); return mp_obj_new_str(mod_network_hostname_data, strlen(mod_network_hostname_data));
} else { } else {
size_t len; size_t len;
const char *str = mp_obj_str_get_data(args[0], &len); const char *str = mp_obj_str_get_data(args[0], &len);
@@ -144,22 +144,15 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_network_hostname_obj, 0, 1, mod_n
#if LWIP_VERSION_MAJOR >= 2 #if LWIP_VERSION_MAJOR >= 2
MP_DEFINE_CONST_FUN_OBJ_KW(mod_network_ipconfig_obj, 0, mod_network_ipconfig); MP_DEFINE_CONST_FUN_OBJ_KW(mod_network_ipconfig_obj, 0, mod_network_ipconfig);
#endif #endif
#if MICROPY_PY_NETWORK_NINAW10
MP_DEFINE_CONST_FUN_OBJ_KW(mod_network_ipconfig_obj, 0, network_ninaw10_ipconfig);
#endif
static const mp_rom_map_elem_t mp_module_network_globals_table[] = { static const mp_rom_map_elem_t mp_module_network_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) }, { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) },
{ MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&mod_network_country_obj) }, { MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&mod_network_country_obj) },
{ MP_ROM_QSTR(MP_QSTR_hostname), MP_ROM_PTR(&mod_network_hostname_obj) }, { MP_ROM_QSTR(MP_QSTR_hostname), MP_ROM_PTR(&mod_network_hostname_obj) },
#if LWIP_VERSION_MAJOR >= 2 || MICROPY_PY_NETWORK_NINAW10 #if LWIP_VERSION_MAJOR >= 2
{ MP_ROM_QSTR(MP_QSTR_ipconfig), MP_ROM_PTR(&mod_network_ipconfig_obj) }, { MP_ROM_QSTR(MP_QSTR_ipconfig), MP_ROM_PTR(&mod_network_ipconfig_obj) },
#endif #endif
#if MICROPY_PY_NETWORK_PPP_LWIP
{ MP_ROM_QSTR(MP_QSTR_PPP), MP_ROM_PTR(&mp_network_ppp_lwip_type) },
#endif
// Defined per port in mpconfigport.h // Defined per port in mpconfigport.h
#ifdef MICROPY_PORT_NETWORK_INTERFACES #ifdef MICROPY_PORT_NETWORK_INTERFACES
{ MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) }, { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) },

View File

@@ -72,10 +72,6 @@ mp_obj_t mod_network_hostname(size_t n_args, const mp_obj_t *args);
#include "lwip/init.h" #include "lwip/init.h"
#if MICROPY_PY_NETWORK_PPP_LWIP
extern const struct _mp_obj_type_t mp_network_ppp_lwip_type;
#endif
struct netif; struct netif;
void mod_network_lwip_init(void); void mod_network_lwip_init(void);
void mod_network_lwip_poll_wrapper(uint32_t ticks_ms); void mod_network_lwip_poll_wrapper(uint32_t ticks_ms);
@@ -87,10 +83,6 @@ extern int mp_mod_network_prefer_dns_use_ip_version;
#endif #endif
#elif defined(MICROPY_PORT_NETWORK_INTERFACES) #elif defined(MICROPY_PORT_NETWORK_INTERFACES)
#if MICROPY_PY_NETWORK_NINAW10
mp_obj_t network_ninaw10_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
#endif
struct _mod_network_socket_obj_t; struct _mod_network_socket_obj_t;
typedef struct _mod_network_nic_protocol_t { typedef struct _mod_network_nic_protocol_t {

View File

@@ -52,20 +52,11 @@
#if MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE #if MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE
#define VIRTIO_DEV_ID 0xFF #define VIRTIO_DEV_ID 0xFF
#if MICROPY_PY_OPENAMP_HOST
#define VIRTIO_DEV_ROLE RPMSG_HOST
#else
#define VIRTIO_DEV_ROLE RPMSG_REMOTE
#endif // MICROPY_PY_OPENAMP_HOST
#define VIRTIO_DEV_FEATURES (1 << VIRTIO_RPMSG_F_NS) #define VIRTIO_DEV_FEATURES (1 << VIRTIO_RPMSG_F_NS)
#define VRING0_ID 0 // VRING0 ID (host to remote) fixed to 0 for linux compatibility #define VRING0_ID 0 // VRING0 ID (host to remote) fixed to 0 for linux compatibility
#define VRING1_ID 1 // VRING1 ID (remote to host) fixed to 1 for linux compatibility #define VRING1_ID 1 // VRING1 ID (remote to host) fixed to 1 for linux compatibility
#if MICROPY_PY_OPENAMP_HOST
#define VRING_NOTIFY_ID VRING0_ID #define VRING_NOTIFY_ID VRING0_ID
#else
#define VRING_NOTIFY_ID VRING1_ID
#endif // MICROPY_PY_OPENAMP_HOST
#define VRING_COUNT 2 #define VRING_COUNT 2
#define VRING_ALIGNMENT 32 #define VRING_ALIGNMENT 32
@@ -80,15 +71,13 @@
#define VRING_BUFF_ADDR (METAL_SHM_ADDR + 0x2000) #define VRING_BUFF_ADDR (METAL_SHM_ADDR + 0x2000)
#define VRING_BUFF_SIZE (METAL_SHM_SIZE - 0x2000) #define VRING_BUFF_SIZE (METAL_SHM_SIZE - 0x2000)
#if MICROPY_PY_OPENAMP_HOST
static const char openamp_trace_buf[128]; static const char openamp_trace_buf[128];
#define MICROPY_PY_OPENAMP_TRACE_BUF ((uint32_t)openamp_trace_buf) #define MICROPY_PY_OPENAMP_TRACE_BUF ((uint32_t)openamp_trace_buf)
#define MICROPY_PY_OPENAMP_TRACE_BUF_LEN sizeof(MICROPY_PY_OPENAMP_TRACE_BUF) #define MICROPY_PY_OPENAMP_TRACE_BUF_LEN sizeof(MICROPY_PY_OPENAMP_TRACE_BUF)
#endif // MICROPY_PY_OPENAMP_HOST
#endif // MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE #endif // MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE
#if MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_REMOTEPROC #if MICROPY_PY_OPENAMP_REMOTEPROC
extern mp_obj_type_t openamp_remoteproc_type; extern mp_obj_type_t openamp_remoteproc_type;
#endif #endif
@@ -192,13 +181,13 @@ static mp_obj_t endpoint_send(uint n_args, const mp_obj_t *pos_args, mp_map_t *k
for (mp_uint_t start = mp_hal_ticks_ms(); ;) { for (mp_uint_t start = mp_hal_ticks_ms(); ;) {
bytes = rpmsg_send_offchannel_raw(&self->ep, src, dest, rbuf.buf, rbuf.len, false); bytes = rpmsg_send_offchannel_raw(&self->ep, src, dest, rbuf.buf, rbuf.len, false);
if (bytes > 0 || timeout == 0) { if (bytes > 0 || timeout == 0) {
mp_event_handle_nowait(); MICROPY_EVENT_POLL_HOOK
break; break;
} }
if (timeout > 0 && (mp_hal_ticks_ms() - start > timeout)) { if (timeout > 0 && (mp_hal_ticks_ms() - start > timeout)) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("timeout waiting for a free buffer")); mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("timeout waiting for a free buffer"));
} }
mp_event_wait_ms(1); MICROPY_EVENT_POLL_HOOK
} }
return mp_obj_new_int(bytes); return mp_obj_new_int(bytes);
} }
@@ -221,7 +210,7 @@ static mp_obj_t endpoint_make_new(const mp_obj_type_t *type, size_t n_args, size
enum { ARG_name, ARG_callback, ARG_src, ARG_dest }; enum { ARG_name, ARG_callback, ARG_src, ARG_dest };
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_name, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE } }, { MP_QSTR_name, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE } },
{ MP_QSTR_callback, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE } }, { MP_QSTR_callback, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE } },
{ MP_QSTR_src, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = RPMSG_ADDR_ANY } }, { MP_QSTR_src, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = RPMSG_ADDR_ANY } },
{ MP_QSTR_dest, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = RPMSG_ADDR_ANY } }, { MP_QSTR_dest, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = RPMSG_ADDR_ANY } },
}; };
@@ -274,15 +263,16 @@ static void openamp_ns_callback(struct rpmsg_device *rdev, const char *name, uin
// the Name Service (NS) announcement containing the name of the channel. // the Name Service (NS) announcement containing the name of the channel.
virtio_dev_obj_t *virtio_device = metal_container_of(rdev, virtio_dev_obj_t, rvdev); virtio_dev_obj_t *virtio_device = metal_container_of(rdev, virtio_dev_obj_t, rvdev);
if (virtio_device->ns_callback != mp_const_none) { if (virtio_device->ns_callback != mp_const_none) {
mp_call_function_2(virtio_device->ns_callback, mp_obj_new_int(dest), mp_obj_new_str_from_cstr(name)); mp_call_function_2(virtio_device->ns_callback, mp_obj_new_int(dest), mp_obj_new_str(name, strlen(name)));
} }
} }
#if MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE #if MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE
// The shared resource table must be initialized manually by the host here, // The shared resource table must be initialized manually by the host here,
// because it's not located in the data region, so the startup code doesn't // because it's not located in the data region, so the startup code doesn't
// know about it. // know about it.
static void openamp_rsc_table_init(openamp_rsc_table_t *rsc_table) { static void openamp_rsc_table_init(openamp_rsc_table_t **rsc_table_out) {
openamp_rsc_table_t *rsc_table = METAL_RSC_ADDR;
memset(rsc_table, 0, METAL_RSC_SIZE); memset(rsc_table, 0, METAL_RSC_SIZE);
rsc_table->version = 1; rsc_table->version = 1;
@@ -309,8 +299,9 @@ static void openamp_rsc_table_init(openamp_rsc_table_t *rsc_table) {
// Flush resource table. // Flush resource table.
metal_cache_flush((uint32_t *)rsc_table, sizeof(openamp_rsc_table_t)); metal_cache_flush((uint32_t *)rsc_table, sizeof(openamp_rsc_table_t));
#endif #endif
*rsc_table_out = rsc_table;
} }
#endif // MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE #endif // MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE
static mp_obj_t openamp_new_service_callback(mp_obj_t ns_callback) { static mp_obj_t openamp_new_service_callback(mp_obj_t ns_callback) {
if (MP_STATE_PORT(virtio_device) == NULL) { if (MP_STATE_PORT(virtio_device) == NULL) {
@@ -351,10 +342,8 @@ void openamp_init(void) {
metal_init(&metal_params); metal_init(&metal_params);
// Initialize the shared resource table. // Initialize the shared resource table.
openamp_rsc_table_t *rsc_table = METAL_RSC_ADDR; openamp_rsc_table_t *rsc_table;
#if MICROPY_PY_OPENAMP_HOST openamp_rsc_table_init(&rsc_table);
openamp_rsc_table_init(rsc_table);
#endif // MICROPY_PY_OPENAMP_HOST
if (metal_register_generic_device(&shm_device) != 0) { if (metal_register_generic_device(&shm_device) != 0) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Failed to register metal device")); mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Failed to register metal device"));
@@ -379,7 +368,7 @@ void openamp_init(void) {
} }
// Create virtio device. // Create virtio device.
struct virtio_device *vdev = rproc_virtio_create_vdev(VIRTIO_DEV_ROLE, VIRTIO_DEV_ID, struct virtio_device *vdev = rproc_virtio_create_vdev(RPMSG_HOST, VIRTIO_DEV_ID,
&rsc_table->vdev, rsc_io, NULL, metal_rproc_notify, NULL); &rsc_table->vdev, rsc_io, NULL, metal_rproc_notify, NULL);
if (vdev == NULL) { if (vdev == NULL) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Failed to create virtio device")); mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Failed to create virtio device"));
@@ -400,8 +389,8 @@ void openamp_init(void) {
// The remote processor detects that the virtio device is ready by polling // The remote processor detects that the virtio device is ready by polling
// the status field in the resource table. // the status field in the resource table.
rpmsg_virtio_init_shm_pool(&virtio_device->shm_pool, (void *)VRING_BUFF_ADDR, (size_t)VRING_BUFF_SIZE); rpmsg_virtio_init_shm_pool(&virtio_device->shm_pool, (void *)VRING_BUFF_ADDR, (size_t)VRING_BUFF_SIZE);
rpmsg_init_vdev(&virtio_device->rvdev, vdev, openamp_ns_callback, shm_io, &virtio_device->shm_pool); rpmsg_init_vdev(&virtio_device->rvdev, vdev, openamp_ns_callback, shm_io, &virtio_device->shm_pool);
MP_STATE_PORT(virtio_device) = virtio_device; MP_STATE_PORT(virtio_device) = virtio_device;
} }
@@ -410,7 +399,7 @@ static const mp_rom_map_elem_t globals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_ENDPOINT_ADDR_ANY), MP_ROM_INT(RPMSG_ADDR_ANY) }, { MP_ROM_QSTR(MP_QSTR_ENDPOINT_ADDR_ANY), MP_ROM_INT(RPMSG_ADDR_ANY) },
{ MP_ROM_QSTR(MP_QSTR_new_service_callback), MP_ROM_PTR(&openamp_new_service_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_new_service_callback), MP_ROM_PTR(&openamp_new_service_callback_obj) },
{ MP_ROM_QSTR(MP_QSTR_Endpoint), MP_ROM_PTR(&endpoint_type) }, { MP_ROM_QSTR(MP_QSTR_Endpoint), MP_ROM_PTR(&endpoint_type) },
#if MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_REMOTEPROC #if MICROPY_PY_OPENAMP_REMOTEPROC
{ MP_ROM_QSTR(MP_QSTR_RemoteProc), MP_ROM_PTR(&openamp_remoteproc_type) }, { MP_ROM_QSTR(MP_QSTR_RemoteProc), MP_ROM_PTR(&openamp_remoteproc_type) },
#endif #endif
}; };

View File

@@ -26,7 +26,7 @@
* OpenAMP's remoteproc class. * OpenAMP's remoteproc class.
*/ */
#if MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_REMOTEPROC #if MICROPY_PY_OPENAMP_REMOTEPROC
#include "py/obj.h" #include "py/obj.h"
#include "py/nlr.h" #include "py/nlr.h"
@@ -137,7 +137,7 @@ mp_obj_t openamp_remoteproc_make_new(const mp_obj_type_t *type, size_t n_args, s
} }
if (mp_obj_is_int(args[ARG_entry].u_obj)) { if (mp_obj_is_int(args[ARG_entry].u_obj)) {
self->rproc.bootaddr = mp_obj_int_get_truncated(args[ARG_entry].u_obj); self->rproc.bootaddr = mp_obj_get_int(args[ARG_entry].u_obj);
} else { } else {
#if MICROPY_PY_OPENAMP_REMOTEPROC_ELFLD_ENABLE #if MICROPY_PY_OPENAMP_REMOTEPROC_ELFLD_ENABLE
// Load firmware. // Load firmware.
@@ -170,4 +170,4 @@ MP_DEFINE_CONST_OBJ_TYPE(
locals_dict, &openamp_remoteproc_dict locals_dict, &openamp_remoteproc_dict
); );
#endif // MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_REMOTEPROC #endif // MICROPY_PY_OPENAMP_REMOTEPROC

View File

@@ -26,7 +26,7 @@
* OpenAMP's remoteproc store. * OpenAMP's remoteproc store.
*/ */
#if MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_REMOTEPROC #if MICROPY_PY_OPENAMP_REMOTEPROC
#include "py/obj.h" #include "py/obj.h"
#include "py/nlr.h" #include "py/nlr.h"
@@ -70,7 +70,7 @@ void *mp_openamp_remoteproc_store_alloc(void) {
static int openamp_remoteproc_store_open(void *store, const char *path, const void **image_data) { static int openamp_remoteproc_store_open(void *store, const char *path, const void **image_data) {
metal_log(METAL_LOG_DEBUG, "store_open(): %s\n", path); metal_log(METAL_LOG_DEBUG, "store_open(): %s\n", path);
mp_obj_t args[2] = { mp_obj_t args[2] = {
mp_obj_new_str_from_cstr(path), mp_obj_new_str(path, strlen(path)),
MP_OBJ_NEW_QSTR(MP_QSTR_rb), MP_OBJ_NEW_QSTR(MP_QSTR_rb),
}; };
@@ -141,4 +141,4 @@ const struct image_store_ops openamp_remoteproc_store_ops = {
#endif // MICROPY_PY_OPENAMP_REMOTEPROC_STORE_ENABLE #endif // MICROPY_PY_OPENAMP_REMOTEPROC_STORE_ENABLE
#endif // MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_REMOTEPROC #endif // MICROPY_PY_OPENAMP_REMOTEPROC

View File

@@ -153,6 +153,9 @@ static const mp_rom_map_elem_t os_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_putenv), MP_ROM_PTR(&mp_os_putenv_obj) }, { MP_ROM_QSTR(MP_QSTR_putenv), MP_ROM_PTR(&mp_os_putenv_obj) },
{ MP_ROM_QSTR(MP_QSTR_unsetenv), MP_ROM_PTR(&mp_os_unsetenv_obj) }, { MP_ROM_QSTR(MP_QSTR_unsetenv), MP_ROM_PTR(&mp_os_unsetenv_obj) },
#endif #endif
#if MICROPY_PY_OS_SEP
{ MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) },
#endif
#if MICROPY_PY_OS_SYNC #if MICROPY_PY_OS_SYNC
{ MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mp_os_sync_obj) }, { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mp_os_sync_obj) },
#endif #endif
@@ -167,7 +170,6 @@ static const mp_rom_map_elem_t os_module_globals_table[] = {
#endif #endif
#if MICROPY_VFS #if MICROPY_VFS
{ MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) },
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) },
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },

View File

@@ -83,9 +83,6 @@
#elif defined(__NEWLIB__) #elif defined(__NEWLIB__)
#define MICROPY_PLATFORM_LIBC_LIB "newlib" #define MICROPY_PLATFORM_LIBC_LIB "newlib"
#define MICROPY_PLATFORM_LIBC_VER _NEWLIB_VERSION #define MICROPY_PLATFORM_LIBC_VER _NEWLIB_VERSION
#elif defined(_PICOLIBC__)
#define MICROPY_PLATFORM_LIBC_LIB "picolibc"
#define MICROPY_PLATFORM_LIBC_VER _PICOLIBC_VERSION
#else #else
#define MICROPY_PLATFORM_LIBC_LIB "" #define MICROPY_PLATFORM_LIBC_LIB ""
#define MICROPY_PLATFORM_LIBC_VER "" #define MICROPY_PLATFORM_LIBC_VER ""

View File

@@ -31,7 +31,7 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "py/binary.h" #include "py/binary.h"
#include "py/objstr.h" #include "py/objstr.h"
#include "py/cstack.h" #include "py/stackctrl.h"
#if MICROPY_PY_BUILTINS_STR_UNICODE #if MICROPY_PY_BUILTINS_STR_UNICODE
#include "py/unicode.h" #include "py/unicode.h"
@@ -39,7 +39,7 @@
#if MICROPY_PY_RE #if MICROPY_PY_RE
#define re1_5_stack_chk() mp_cstack_check() #define re1_5_stack_chk() MP_STACK_CHECK()
#include "lib/re1.5/re1.5.h" #include "lib/re1.5/re1.5.h"
@@ -194,8 +194,7 @@ static void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
mp_printf(print, "<re %p>", self); mp_printf(print, "<re %p>", self);
} }
// Note: this function can't be named re_exec because it may clash with system headers, eg on FreeBSD static mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
static mp_obj_t re_exec_helper(bool is_anchored, uint n_args, const mp_obj_t *args) {
(void)n_args; (void)n_args;
mp_obj_re_t *self; mp_obj_re_t *self;
if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) { if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) {
@@ -224,12 +223,12 @@ static mp_obj_t re_exec_helper(bool is_anchored, uint n_args, const mp_obj_t *ar
} }
static mp_obj_t re_match(size_t n_args, const mp_obj_t *args) { static mp_obj_t re_match(size_t n_args, const mp_obj_t *args) {
return re_exec_helper(true, n_args, args); return re_exec(true, n_args, args);
} }
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_match_obj, 2, 4, re_match); MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_match_obj, 2, 4, re_match);
static mp_obj_t re_search(size_t n_args, const mp_obj_t *args) { static mp_obj_t re_search(size_t n_args, const mp_obj_t *args) {
return re_exec_helper(false, n_args, args); return re_exec(false, n_args, args);
} }
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_search_obj, 2, 4, re_search); MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_search_obj, 2, 4, re_search);

View File

@@ -53,10 +53,6 @@
#else #else
#include "mbedtls/version.h" #include "mbedtls/version.h"
#endif #endif
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
#include "mbedtls/ecdsa.h"
#include "mbedtls/asn1.h"
#endif
#define MP_STREAM_POLL_RDWR (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR) #define MP_STREAM_POLL_RDWR (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)
@@ -72,9 +68,6 @@ typedef struct _mp_obj_ssl_context_t {
int authmode; int authmode;
int *ciphersuites; int *ciphersuites;
mp_obj_t handler; mp_obj_t handler;
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
mp_obj_t ecdsa_sign_callback;
#endif
} mp_obj_ssl_context_t; } mp_obj_ssl_context_t;
// This corresponds to an SSLSocket object. // This corresponds to an SSLSocket object.
@@ -107,23 +100,6 @@ static void mbedtls_debug(void *ctx, int level, const char *file, int line, cons
} }
#endif #endif
// Given a string-like object holding PEM or DER formatted ASN.1 data, return a
// pointer to its buffer and the correct length for mbedTLS APIs.
//
// (mbedTLS >= 3.5 rejects DER formatted data with trailing bytes within keylen,
// but PEM must include a terminating NUL byte in the keylen...)
static const unsigned char *asn1_get_data(mp_obj_t obj, size_t *out_len) {
size_t len;
const char *str = mp_obj_str_get_data(obj, &len);
#if defined(MBEDTLS_PEM_PARSE_C)
if (strstr(str, "-----BEGIN ") != NULL) {
++len;
}
#endif
*out_len = len;
return (const unsigned char *)str;
}
static NORETURN void mbedtls_raise_error(int err) { static NORETURN void mbedtls_raise_error(int err) {
// Handle special cases. // Handle special cases.
if (err == MBEDTLS_ERR_SSL_ALLOC_FAILED) { if (err == MBEDTLS_ERR_SSL_ALLOC_FAILED) {
@@ -173,13 +149,6 @@ static NORETURN void mbedtls_raise_error(int err) {
#endif #endif
} }
// Stores the current SSLContext for use in mbedtls callbacks where the current state is not passed.
static inline void store_active_context(mp_obj_ssl_context_t *ssl_context) {
#if MICROPY_PY_SSL_MBEDTLS_NEED_ACTIVE_CONTEXT
MP_STATE_THREAD(tls_ssl_context) = ssl_context;
#endif
}
static void ssl_check_async_handshake_failure(mp_obj_ssl_socket_t *sslsock, int *errcode) { static void ssl_check_async_handshake_failure(mp_obj_ssl_socket_t *sslsock, int *errcode) {
if ( if (
#if MBEDTLS_VERSION_NUMBER >= 0x03000000 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
@@ -255,9 +224,6 @@ static mp_obj_t ssl_context_make_new(const mp_obj_type_t *type_in, size_t n_args
mbedtls_pk_init(&self->pkey); mbedtls_pk_init(&self->pkey);
self->ciphersuites = NULL; self->ciphersuites = NULL;
self->handler = mp_const_none; self->handler = mp_const_none;
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
self->ecdsa_sign_callback = mp_const_none;
#endif
#ifdef MBEDTLS_DEBUG_C #ifdef MBEDTLS_DEBUG_C
// Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose // Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose
@@ -305,10 +271,6 @@ static void ssl_context_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
dest[0] = MP_OBJ_NEW_SMALL_INT(self->authmode); dest[0] = MP_OBJ_NEW_SMALL_INT(self->authmode);
} else if (attr == MP_QSTR_verify_callback) { } else if (attr == MP_QSTR_verify_callback) {
dest[0] = self->handler; dest[0] = self->handler;
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
} else if (attr == MP_QSTR_ecdsa_sign_callback) {
dest[0] = self->ecdsa_sign_callback;
#endif
} else { } else {
// Continue lookup in locals_dict. // Continue lookup in locals_dict.
dest[1] = MP_OBJ_SENTINEL; dest[1] = MP_OBJ_SENTINEL;
@@ -319,11 +281,6 @@ static void ssl_context_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
self->authmode = mp_obj_get_int(dest[1]); self->authmode = mp_obj_get_int(dest[1]);
dest[0] = MP_OBJ_NULL; dest[0] = MP_OBJ_NULL;
mbedtls_ssl_conf_authmode(&self->conf, self->authmode); mbedtls_ssl_conf_authmode(&self->conf, self->authmode);
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
} else if (attr == MP_QSTR_ecdsa_sign_callback) {
dest[0] = MP_OBJ_NULL;
self->ecdsa_sign_callback = dest[1];
#endif
} else if (attr == MP_QSTR_verify_callback) { } else if (attr == MP_QSTR_verify_callback) {
dest[0] = MP_OBJ_NULL; dest[0] = MP_OBJ_NULL;
self->handler = dest[1]; self->handler = dest[1];
@@ -350,7 +307,7 @@ static mp_obj_t ssl_context_get_ciphers(mp_obj_t self_in) {
mp_obj_t list = mp_obj_new_list(0, NULL); mp_obj_t list = mp_obj_new_list(0, NULL);
for (const int *cipher_list = mbedtls_ssl_list_ciphersuites(); *cipher_list; ++cipher_list) { for (const int *cipher_list = mbedtls_ssl_list_ciphersuites(); *cipher_list; ++cipher_list) {
const char *cipher_name = mbedtls_ssl_get_ciphersuite_name(*cipher_list); const char *cipher_name = mbedtls_ssl_get_ciphersuite_name(*cipher_list);
mp_obj_list_append(list, MP_OBJ_FROM_PTR(mp_obj_new_str_from_cstr(cipher_name))); mp_obj_list_append(list, MP_OBJ_FROM_PTR(mp_obj_new_str(cipher_name, strlen(cipher_name))));
} }
return list; return list;
} }
@@ -389,20 +346,22 @@ static MP_DEFINE_CONST_FUN_OBJ_2(ssl_context_set_ciphers_obj, ssl_context_set_ci
static void ssl_context_load_key(mp_obj_ssl_context_t *self, mp_obj_t key_obj, mp_obj_t cert_obj) { static void ssl_context_load_key(mp_obj_ssl_context_t *self, mp_obj_t key_obj, mp_obj_t cert_obj) {
size_t key_len; size_t key_len;
const unsigned char *key = asn1_get_data(key_obj, &key_len); const byte *key = (const byte *)mp_obj_str_get_data(key_obj, &key_len);
// len should include terminating null
int ret; int ret;
#if MBEDTLS_VERSION_NUMBER >= 0x03000000 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
ret = mbedtls_pk_parse_key(&self->pkey, key, key_len, NULL, 0, mbedtls_ctr_drbg_random, &self->ctr_drbg); ret = mbedtls_pk_parse_key(&self->pkey, key, key_len + 1, NULL, 0, mbedtls_ctr_drbg_random, &self->ctr_drbg);
#else #else
ret = mbedtls_pk_parse_key(&self->pkey, key, key_len, NULL, 0); ret = mbedtls_pk_parse_key(&self->pkey, key, key_len + 1, NULL, 0);
#endif #endif
if (ret != 0) { if (ret != 0) {
mbedtls_raise_error(MBEDTLS_ERR_PK_BAD_INPUT_DATA); // use general error for all key errors mbedtls_raise_error(MBEDTLS_ERR_PK_BAD_INPUT_DATA); // use general error for all key errors
} }
size_t cert_len; size_t cert_len;
const unsigned char *cert = asn1_get_data(cert_obj, &cert_len); const byte *cert = (const byte *)mp_obj_str_get_data(cert_obj, &cert_len);
ret = mbedtls_x509_crt_parse(&self->cert, cert, cert_len); // len should include terminating null
ret = mbedtls_x509_crt_parse(&self->cert, cert, cert_len + 1);
if (ret != 0) { if (ret != 0) {
mbedtls_raise_error(MBEDTLS_ERR_X509_BAD_INPUT_DATA); // use general error for all cert errors mbedtls_raise_error(MBEDTLS_ERR_X509_BAD_INPUT_DATA); // use general error for all cert errors
} }
@@ -423,8 +382,9 @@ static MP_DEFINE_CONST_FUN_OBJ_3(ssl_context_load_cert_chain_obj, ssl_context_lo
static void ssl_context_load_cadata(mp_obj_ssl_context_t *self, mp_obj_t cadata_obj) { static void ssl_context_load_cadata(mp_obj_ssl_context_t *self, mp_obj_t cadata_obj) {
size_t cacert_len; size_t cacert_len;
const unsigned char *cacert = asn1_get_data(cadata_obj, &cacert_len); const byte *cacert = (const byte *)mp_obj_str_get_data(cadata_obj, &cacert_len);
int ret = mbedtls_x509_crt_parse(&self->cacert, cacert, cacert_len); // len should include terminating null
int ret = mbedtls_x509_crt_parse(&self->cacert, cacert, cacert_len + 1);
if (ret != 0) { if (ret != 0) {
mbedtls_raise_error(MBEDTLS_ERR_X509_BAD_INPUT_DATA); // use general error for all cert errors mbedtls_raise_error(MBEDTLS_ERR_X509_BAD_INPUT_DATA); // use general error for all cert errors
} }
@@ -523,9 +483,6 @@ static int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) {
static mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t sock, static mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t sock,
bool server_side, bool do_handshake_on_connect, mp_obj_t server_hostname) { bool server_side, bool do_handshake_on_connect, mp_obj_t server_hostname) {
// Store the current SSL context.
store_active_context(ssl_context);
// Verify the socket object has the full stream protocol // Verify the socket object has the full stream protocol
mp_get_stream_raise(sock, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); mp_get_stream_raise(sock, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
@@ -615,8 +572,8 @@ static mp_obj_t mod_ssl_cipher(mp_obj_t o_in) {
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in); mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
const char *cipher_suite = mbedtls_ssl_get_ciphersuite(&o->ssl); const char *cipher_suite = mbedtls_ssl_get_ciphersuite(&o->ssl);
const char *tls_version = mbedtls_ssl_get_version(&o->ssl); const char *tls_version = mbedtls_ssl_get_version(&o->ssl);
mp_obj_t tuple[2] = {mp_obj_new_str_from_cstr(cipher_suite), mp_obj_t tuple[2] = {mp_obj_new_str(cipher_suite, strlen(cipher_suite)),
mp_obj_new_str_from_cstr(tls_version)}; mp_obj_new_str(tls_version, strlen(tls_version))};
return mp_obj_new_tuple(2, tuple); return mp_obj_new_tuple(2, tuple);
} }
@@ -631,9 +588,6 @@ static mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
return MP_STREAM_ERROR; return MP_STREAM_ERROR;
} }
// Store the current SSL context.
store_active_context(o->ssl_context);
int ret = mbedtls_ssl_read(&o->ssl, buf, size); int ret = mbedtls_ssl_read(&o->ssl, buf, size);
if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
// end of stream // end of stream
@@ -675,9 +629,6 @@ static mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
return MP_STREAM_ERROR; return MP_STREAM_ERROR;
} }
// Store the current SSL context.
store_active_context(o->ssl_context);
int ret = mbedtls_ssl_write(&o->ssl, buf, size); int ret = mbedtls_ssl_write(&o->ssl, buf, size);
if (ret >= 0) { if (ret >= 0) {
return ret; return ret;
@@ -715,9 +666,6 @@ static mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i
mp_obj_t sock = self->sock; mp_obj_t sock = self->sock;
if (request == MP_STREAM_CLOSE) { if (request == MP_STREAM_CLOSE) {
// Clear the SSL context.
store_active_context(NULL);
if (sock == MP_OBJ_NULL) { if (sock == MP_OBJ_NULL) {
// Already closed socket, do nothing. // Already closed socket, do nothing.
return 0; return 0;
@@ -805,57 +753,6 @@ static MP_DEFINE_CONST_OBJ_TYPE(
/******************************************************************************/ /******************************************************************************/
// ssl module. // ssl module.
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
int micropy_mbedtls_ecdsa_sign_alt(const mbedtls_mpi *d, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t sig_size, size_t *slen) {
uint8_t key[256];
// Check if the current context has an alternative sign function.
mp_obj_ssl_context_t *ssl_ctx = MP_STATE_THREAD(tls_ssl_context);
if (ssl_ctx == NULL || ssl_ctx->ecdsa_sign_callback == mp_const_none) {
return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
}
size_t klen = mbedtls_mpi_size(d);
if (klen > sizeof(key)) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
// Convert the MPI private key (d) to a binary array
if (mbedtls_mpi_write_binary(d, key, klen) != 0) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
nlr_buf_t nlr;
mp_buffer_info_t sig_buf;
if (nlr_push(&nlr) == 0) {
mp_obj_t ret = mp_call_function_2(ssl_ctx->ecdsa_sign_callback,
mp_obj_new_bytearray_by_ref(klen, (void *)key),
mp_obj_new_bytearray_by_ref(hlen, (void *)hash));
if (ret == mp_const_none) {
// key couldn't be used by the alternative implementation.
nlr_pop();
return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
}
mp_get_buffer_raise(ret, &sig_buf, MP_BUFFER_READ);
nlr_pop();
} else {
// The alternative implementation failed to sign.
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
// Check if the buffer fits.
if (sig_buf.len > sig_size) {
return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
}
// Copy ASN.1 signature to buffer.
*slen = sig_buf.len;
memcpy(sig, sig_buf.buf, sig_buf.len);
return 0;
}
#endif
static const mp_rom_map_elem_t mp_module_tls_globals_table[] = { static const mp_rom_map_elem_t mp_module_tls_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_tls) }, { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_tls) },

View File

@@ -143,10 +143,6 @@ static inline mp_uint_t uctypes_struct_scalar_size(int val_type) {
// Get size of aggregate type descriptor // Get size of aggregate type descriptor
static mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_uint_t *max_field_size) { static mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_uint_t *max_field_size) {
if (t->len == 0) {
syntax_error();
}
mp_uint_t total_size = 0; mp_uint_t total_size = 0;
mp_int_t offset_ = MP_OBJ_SMALL_INT_VALUE(t->items[0]); mp_int_t offset_ = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
@@ -154,15 +150,8 @@ static mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_
switch (agg_type) { switch (agg_type) {
case STRUCT: case STRUCT:
if (t->len != 2) {
syntax_error();
}
return uctypes_struct_size(t->items[1], layout_type, max_field_size); return uctypes_struct_size(t->items[1], layout_type, max_field_size);
case PTR: case PTR:
// Second field ignored, but should still be present for consistency.
if (t->len != 2) {
syntax_error();
}
if (sizeof(void *) > *max_field_size) { if (sizeof(void *) > *max_field_size) {
*max_field_size = sizeof(void *); *max_field_size = sizeof(void *);
} }
@@ -178,17 +167,15 @@ static mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_
if (item_s > *max_field_size) { if (item_s > *max_field_size) {
*max_field_size = item_s; *max_field_size = item_s;
} }
} else if (t->len == 3) { } else {
// Elements of array are aggregates // Elements of array are aggregates
item_s = uctypes_struct_size(t->items[2], layout_type, max_field_size); item_s = uctypes_struct_size(t->items[2], layout_type, max_field_size);
} else {
syntax_error();
} }
return item_s * arr_sz; return item_s * arr_sz;
} }
default: default:
syntax_error(); assert(0);
} }
return total_size; return total_size;

View File

@@ -146,7 +146,7 @@ static void handle_op(mp_obj_webrepl_t *self) {
// Handle operations requiring opened file // Handle operations requiring opened file
mp_obj_t open_args[2] = { mp_obj_t open_args[2] = {
mp_obj_new_str_from_cstr(self->hdr.fname), mp_obj_new_str(self->hdr.fname, strlen(self->hdr.fname)),
MP_OBJ_NEW_QSTR(MP_QSTR_rb) MP_OBJ_NEW_QSTR(MP_QSTR_rb)
}; };

View File

@@ -60,10 +60,6 @@ typedef struct _network_cyw43_obj_t {
static const network_cyw43_obj_t network_cyw43_wl_sta = { { &mp_network_cyw43_type }, &cyw43_state, CYW43_ITF_STA }; static const network_cyw43_obj_t network_cyw43_wl_sta = { { &mp_network_cyw43_type }, &cyw43_state, CYW43_ITF_STA };
static const network_cyw43_obj_t network_cyw43_wl_ap = { { &mp_network_cyw43_type }, &cyw43_state, CYW43_ITF_AP }; static const network_cyw43_obj_t network_cyw43_wl_ap = { { &mp_network_cyw43_type }, &cyw43_state, CYW43_ITF_AP };
// Avoid race conditions with callbacks by tracking the last up or down request
// we have made for each interface.
static bool if_active[2];
static void network_cyw43_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { static void network_cyw43_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in);
struct netif *netif = &self->cyw->netif[self->itf]; struct netif *netif = &self->cyw->netif[self->itf];
@@ -126,10 +122,6 @@ static MP_DEFINE_CONST_FUN_OBJ_3(network_cyw43_ioctl_obj, network_cyw43_ioctl);
/*******************************************************************************/ /*******************************************************************************/
// network API // network API
static uint32_t get_country_code(void) {
return CYW43_COUNTRY(mod_network_country_code[0], mod_network_country_code[1], 0);
}
static mp_obj_t network_cyw43_deinit(mp_obj_t self_in) { static mp_obj_t network_cyw43_deinit(mp_obj_t self_in) {
network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in);
cyw43_deinit(self->cyw); cyw43_deinit(self->cyw);
@@ -140,11 +132,10 @@ static MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_deinit_obj, network_cyw43_deinit)
static mp_obj_t network_cyw43_active(size_t n_args, const mp_obj_t *args) { static mp_obj_t network_cyw43_active(size_t n_args, const mp_obj_t *args) {
network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]); network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (n_args == 1) { if (n_args == 1) {
return mp_obj_new_bool(if_active[self->itf]); return mp_obj_new_bool(cyw43_tcpip_link_status(self->cyw, self->itf));
} else { } else {
bool value = mp_obj_is_true(args[1]); uint32_t country = CYW43_COUNTRY(mod_network_country_code[0], mod_network_country_code[1], 0);
cyw43_wifi_set_up(self->cyw, self->itf, value, get_country_code()); cyw43_wifi_set_up(self->cyw, self->itf, mp_obj_is_true(args[1]), country);
if_active[self->itf] = value;
return mp_const_none; return mp_const_none;
} }
} }
@@ -320,17 +311,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_disconnect_obj, network_cyw43_dis
static mp_obj_t network_cyw43_isconnected(mp_obj_t self_in) { static mp_obj_t network_cyw43_isconnected(mp_obj_t self_in) {
network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in);
bool result = (cyw43_tcpip_link_status(self->cyw, self->itf) == CYW43_LINK_UP); return mp_obj_new_bool(cyw43_tcpip_link_status(self->cyw, self->itf) == 3);
if (result && self->itf == CYW43_ITF_AP) {
// For AP we need to not only know if the link is up, but also if any stations
// have associated.
uint8_t mac_buf[6];
int num_stas = 1;
cyw43_wifi_ap_get_stas(self->cyw, &num_stas, mac_buf);
result = num_stas > 0;
}
return mp_obj_new_bool(result);
} }
static MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_isconnected_obj, network_cyw43_isconnected); static MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_isconnected_obj, network_cyw43_isconnected);
@@ -370,15 +351,13 @@ static mp_obj_t network_cyw43_status(size_t n_args, const mp_obj_t *args) {
if (self->itf != CYW43_ITF_AP) { if (self->itf != CYW43_ITF_AP) {
mp_raise_ValueError(MP_ERROR_TEXT("AP required")); mp_raise_ValueError(MP_ERROR_TEXT("AP required"));
} }
static const unsigned mac_len = 6; int num_stas;
static const unsigned max_stas = 32; uint8_t macs[32 * 6];
int num_stas = max_stas;
uint8_t macs[max_stas * mac_len];
cyw43_wifi_ap_get_stas(self->cyw, &num_stas, macs); cyw43_wifi_ap_get_stas(self->cyw, &num_stas, macs);
mp_obj_t list = mp_obj_new_list(num_stas, NULL); mp_obj_t list = mp_obj_new_list(num_stas, NULL);
for (int i = 0; i < num_stas; ++i) { for (int i = 0; i < num_stas; ++i) {
mp_obj_t tuple[1] = { mp_obj_t tuple[1] = {
mp_obj_new_bytes(&macs[i * mac_len], mac_len), mp_obj_new_bytes(&macs[i * 6], 6),
}; };
((mp_obj_list_t *)MP_OBJ_TO_PTR(list))->items[i] = mp_obj_new_tuple(1, tuple); ((mp_obj_list_t *)MP_OBJ_TO_PTR(list))->items[i] = mp_obj_new_tuple(1, tuple);
} }
@@ -466,10 +445,6 @@ static mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
mp_raise_TypeError(MP_ERROR_TEXT("can't specify pos and kw args")); mp_raise_TypeError(MP_ERROR_TEXT("can't specify pos and kw args"));
} }
// A number of these options only update buffers in memory, and
// won't do anything until the interface is cycled down and back up
bool cycle_active = false;
for (size_t i = 0; i < kwargs->alloc; ++i) { for (size_t i = 0; i < kwargs->alloc; ++i) {
if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) { if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) {
mp_map_elem_t *e = &kwargs->table[i]; mp_map_elem_t *e = &kwargs->table[i];
@@ -482,7 +457,6 @@ static mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
} }
case MP_QSTR_channel: { case MP_QSTR_channel: {
cyw43_wifi_ap_set_channel(self->cyw, mp_obj_get_int(e->value)); cyw43_wifi_ap_set_channel(self->cyw, mp_obj_get_int(e->value));
cycle_active = true;
break; break;
} }
case MP_QSTR_ssid: case MP_QSTR_ssid:
@@ -490,7 +464,6 @@ static mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
size_t len; size_t len;
const char *str = mp_obj_str_get_data(e->value, &len); const char *str = mp_obj_str_get_data(e->value, &len);
cyw43_wifi_ap_set_ssid(self->cyw, len, (const uint8_t *)str); cyw43_wifi_ap_set_ssid(self->cyw, len, (const uint8_t *)str);
cycle_active = true;
break; break;
} }
case MP_QSTR_monitor: { case MP_QSTR_monitor: {
@@ -510,7 +483,6 @@ static mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
} }
case MP_QSTR_security: { case MP_QSTR_security: {
cyw43_wifi_ap_set_auth(self->cyw, mp_obj_get_int(e->value)); cyw43_wifi_ap_set_auth(self->cyw, mp_obj_get_int(e->value));
cycle_active = true;
break; break;
} }
case MP_QSTR_key: case MP_QSTR_key:
@@ -518,7 +490,6 @@ static mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
size_t len; size_t len;
const char *str = mp_obj_str_get_data(e->value, &len); const char *str = mp_obj_str_get_data(e->value, &len);
cyw43_wifi_ap_set_password(self->cyw, len, (const uint8_t *)str); cyw43_wifi_ap_set_password(self->cyw, len, (const uint8_t *)str);
cycle_active = true;
break; break;
} }
case MP_QSTR_pm: { case MP_QSTR_pm: {
@@ -548,13 +519,6 @@ static mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
} }
} }
// If the interface is already active, cycle it down and up
if (cycle_active && if_active[self->itf]) {
uint32_t country = get_country_code();
cyw43_wifi_set_up(self->cyw, self->itf, false, country);
cyw43_wifi_set_up(self->cyw, self->itf, true, country);
}
return mp_const_none; return mp_const_none;
} }
} }

View File

@@ -230,7 +230,7 @@ static mp_obj_t network_esp_hosted_config(size_t n_args, const mp_obj_t *args, m
case MP_QSTR_essid: { case MP_QSTR_essid: {
esp_hosted_netinfo_t netinfo; esp_hosted_netinfo_t netinfo;
esp_hosted_wifi_netinfo(&netinfo); esp_hosted_wifi_netinfo(&netinfo);
return mp_obj_new_str_from_cstr(netinfo.ssid); return mp_obj_new_str(netinfo.ssid, strlen(netinfo.ssid));
} }
case MP_QSTR_security: { case MP_QSTR_security: {
esp_hosted_netinfo_t netinfo; esp_hosted_netinfo_t netinfo;

View File

@@ -113,7 +113,7 @@ mp_obj_t mod_network_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwa
case MP_QSTR_dns: { case MP_QSTR_dns: {
char addr_str[IPADDR_STRLEN_MAX]; char addr_str[IPADDR_STRLEN_MAX];
ipaddr_ntoa_r(dns_getserver(0), addr_str, sizeof(addr_str)); ipaddr_ntoa_r(dns_getserver(0), addr_str, sizeof(addr_str));
return mp_obj_new_str_from_cstr(addr_str); return mp_obj_new_str(addr_str, strlen(addr_str));
} }
case MP_QSTR_prefer: { case MP_QSTR_prefer: {
return MP_OBJ_NEW_SMALL_INT(mp_mod_network_prefer_dns_use_ip_version); return MP_OBJ_NEW_SMALL_INT(mp_mod_network_prefer_dns_use_ip_version);
@@ -219,7 +219,7 @@ mp_obj_t mod_network_nic_ipconfig(struct netif *netif, size_t n_args, const mp_o
char addr_str[IPADDR_STRLEN_MAX]; char addr_str[IPADDR_STRLEN_MAX];
ipaddr_ntoa_r(netif_ip_addr6(netif, i), addr_str, sizeof(addr_str)); ipaddr_ntoa_r(netif_ip_addr6(netif, i), addr_str, sizeof(addr_str));
mp_obj_t tuple[4] = { mp_obj_t tuple[4] = {
mp_obj_new_str_from_cstr(addr_str), mp_obj_new_str(addr_str, strlen(addr_str)),
MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_state(netif, i)), MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_state(netif, i)),
MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_pref_life(netif, i)), // preferred MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_pref_life(netif, i)), // preferred
MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_valid_life(netif, i)) MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_valid_life(netif, i))
@@ -297,23 +297,20 @@ mp_obj_t mod_network_nic_ipconfig(struct netif *netif, size_t n_args, const mp_o
char plain_ip[IPADDR_STRLEN_MAX]; char plain_ip[IPADDR_STRLEN_MAX];
char *split = strchr(input_str, '/'); char *split = strchr(input_str, '/');
const char *addr_str = input_str; const char *addr_str = input_str;
int to_copy = MIN(sizeof(plain_ip) - 1, addr_len);
memcpy(plain_ip, addr_str, to_copy);
if (split) { if (split) {
int to_copy = sizeof(plain_ip) - 1;
if (split - addr_str < to_copy) { if (split - addr_str < to_copy) {
to_copy = split - addr_str; to_copy = split - addr_str;
} }
memcpy(plain_ip, addr_str, to_copy);
mp_obj_t prefix_obj = mp_parse_num_integer(split + 1, strlen(split + 1), 10, NULL); mp_obj_t prefix_obj = mp_parse_num_integer(split + 1, strlen(split + 1), 10, NULL);
prefix_bits = mp_obj_get_int(prefix_obj); prefix_bits = mp_obj_get_int(prefix_obj);
if (mp_obj_str_get_qstr(args[0]) == MP_QSTR_addr4) {
uint32_t mask = -(1u << (32 - prefix_bits));
ip_addr_set_ip4_u32_val(netmask, ((mask & 0xFF) << 24) | ((mask & 0xFF00) << 8) | ((mask >> 8) & 0xFF00) | ((mask >> 24) & 0xFF));
}
} else {
netmask = netif->netmask;
} }
plain_ip[to_copy] = '\0'; if (mp_obj_str_get_qstr(args[0]) == MP_QSTR_addr4) {
if (!ipaddr_aton(plain_ip, &ip_addr)) { uint32_t mask = -(1u << (32 - prefix_bits));
ip_addr_set_ip4_u32_val(netmask, ((mask & 0xFF) << 24) | ((mask & 0xFF00) << 8) | ((mask >> 8) & 0xFF00) | ((mask >> 24) & 0xFF));
}
if (!ipaddr_aton(addr_str, &ip_addr)) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid arguments")); mp_raise_ValueError(MP_ERROR_TEXT("invalid arguments"));
} }
if ((mp_obj_str_get_qstr(args[0]) == MP_QSTR_addr6) != IP_IS_V6(&ip_addr) if ((mp_obj_str_get_qstr(args[0]) == MP_QSTR_addr6) != IP_IS_V6(&ip_addr)

View File

@@ -41,7 +41,6 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "py/misc.h" #include "py/misc.h"
#include "py/mperrno.h" #include "py/mperrno.h"
#include "py/parsenum.h"
#include "shared/netutils/netutils.h" #include "shared/netutils/netutils.h"
#include "shared/runtime/softtimer.h" #include "shared/runtime/softtimer.h"
#include "extmod/modnetwork.h" #include "extmod/modnetwork.h"
@@ -76,8 +75,6 @@ typedef struct _nina_obj_t {
#define SO_NO_CHECK (0x100a) #define SO_NO_CHECK (0x100a)
#define NINAW10_POLL_INTERVAL (100) #define NINAW10_POLL_INTERVAL (100)
#define IPADDR_STRLEN_MAX 46
#define is_nonblocking_error(errno) ((errno) == MP_EAGAIN || (errno) == MP_EWOULDBLOCK || (errno) == MP_EINPROGRESS) #define is_nonblocking_error(errno) ((errno) == MP_EAGAIN || (errno) == MP_EWOULDBLOCK || (errno) == MP_EINPROGRESS)
#define debug_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__) #define debug_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__)
@@ -90,8 +87,6 @@ static mp_sched_node_t mp_wifi_poll_node;
static soft_timer_entry_t mp_wifi_poll_timer; static soft_timer_entry_t mp_wifi_poll_timer;
static void network_ninaw10_deinit(void); static void network_ninaw10_deinit(void);
static bool network_ninaw10_dhcp_active = false;
static bool network_ninaw10_poll_list_is_empty(void) { static bool network_ninaw10_poll_list_is_empty(void) {
return MP_STATE_PORT(mp_wifi_poll_list) == NULL || return MP_STATE_PORT(mp_wifi_poll_list) == NULL ||
MP_STATE_PORT(mp_wifi_poll_list)->len == 0; MP_STATE_PORT(mp_wifi_poll_list)->len == 0;
@@ -204,7 +199,6 @@ static mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) {
mp_raise_msg_varg(&mp_type_OSError, mp_raise_msg_varg(&mp_type_OSError,
MP_ERROR_TEXT("failed to initialize Nina-W10 module, error: %d"), error); MP_ERROR_TEXT("failed to initialize Nina-W10 module, error: %d"), error);
} }
network_ninaw10_dhcp_active = true;
// check firmware version // check firmware version
uint8_t semver[NINA_FW_VER_LEN]; uint8_t semver[NINA_FW_VER_LEN];
if (nina_fw_version(semver) != 0) { if (nina_fw_version(semver) != 0) {
@@ -266,7 +260,7 @@ static mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_key, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_key, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = NINA_SEC_WPA_PSK} }, { MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
}; };
@@ -277,6 +271,7 @@ static mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
// get ssid // get ssid
const char *ssid = mp_obj_str_get_str(args[ARG_ssid].u_obj); const char *ssid = mp_obj_str_get_str(args[ARG_ssid].u_obj);
if (strlen(ssid) == 0) { if (strlen(ssid) == 0) {
mp_raise_ValueError(MP_ERROR_TEXT("SSID can't be empty")); mp_raise_ValueError(MP_ERROR_TEXT("SSID can't be empty"));
} }
@@ -289,6 +284,12 @@ static mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
// get security mode // get security mode
mp_uint_t security = args[ARG_security].u_int; mp_uint_t security = args[ARG_security].u_int;
if (security == -1 && self->itf == MOD_NETWORK_STA_IF) {
security = NINA_SEC_WPA_PSK;
} else if (security == -1 && self->itf == MOD_NETWORK_AP_IF) {
security = NINA_SEC_WEP;
}
// Ensure that the key is not empty if a security mode is used. // Ensure that the key is not empty if a security mode is used.
if (security != NINA_SEC_OPEN && strlen(key) == 0) { if (security != NINA_SEC_OPEN && strlen(key) == 0) {
mp_raise_ValueError(MP_ERROR_TEXT("key can't be empty")); mp_raise_ValueError(MP_ERROR_TEXT("key can't be empty"));
@@ -319,6 +320,11 @@ static mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL); soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL);
} else { } else {
mp_uint_t channel = args[ARG_channel].u_int; mp_uint_t channel = args[ARG_channel].u_int;
if (security != NINA_SEC_OPEN && security != NINA_SEC_WEP) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("AP mode only supports WEP or OPEN security modes"));
}
// Initialize WiFi in AP mode. // Initialize WiFi in AP mode.
if (nina_start_ap(ssid, security, key, channel) != 0) { if (nina_start_ap(ssid, security, key, channel) != 0) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("failed to start in AP mode")); mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("failed to start in AP mode"));
@@ -361,155 +367,11 @@ static mp_obj_t network_ninaw10_ifconfig(size_t n_args, const mp_obj_t *args) {
netutils_parse_ipv4_addr(items[2], ifconfig.gateway_addr, NETUTILS_BIG); netutils_parse_ipv4_addr(items[2], ifconfig.gateway_addr, NETUTILS_BIG);
netutils_parse_ipv4_addr(items[3], ifconfig.dns_addr, NETUTILS_BIG); netutils_parse_ipv4_addr(items[3], ifconfig.dns_addr, NETUTILS_BIG);
nina_ifconfig(&ifconfig, true); nina_ifconfig(&ifconfig, true);
network_ninaw10_dhcp_active = false;
return mp_const_none; return mp_const_none;
} }
} }
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_ninaw10_ifconfig_obj, 1, 2, network_ninaw10_ifconfig); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_ninaw10_ifconfig_obj, 1, 2, network_ninaw10_ifconfig);
mp_obj_t network_ninaw10_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
nina_ifconfig_t ifconfig;
// get ifconfig info
nina_ifconfig(&ifconfig, false);
if (kwargs->used == 0) {
// Get config value
if (n_args != 1) {
mp_raise_TypeError(MP_ERROR_TEXT("must query one param"));
}
switch (mp_obj_str_get_qstr(args[0])) {
case MP_QSTR_dns: {
return netutils_format_ipv4_addr(ifconfig.dns_addr, NETUTILS_BIG);
}
default: {
mp_raise_ValueError(MP_ERROR_TEXT("unexpected key"));
break;
}
}
} else {
// Set config value(s)
if (n_args != 0) {
mp_raise_TypeError(MP_ERROR_TEXT("can't specify pos and kw args"));
}
for (size_t i = 0; i < kwargs->alloc; ++i) {
if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) {
mp_map_elem_t *e = &kwargs->table[i];
switch (mp_obj_str_get_qstr(e->key)) {
case MP_QSTR_dns: {
netutils_parse_ipv4_addr(e->value, ifconfig.dns_addr, NETUTILS_BIG);
nina_ifconfig(&ifconfig, true);
break;
}
default: {
mp_raise_ValueError(MP_ERROR_TEXT("unexpected key"));
break;
}
}
}
}
}
return mp_const_none;
}
static mp_obj_t network_ninaw10_nic_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
nina_ifconfig_t ifconfig;
// get ifconfig info
nina_ifconfig(&ifconfig, false);
if (kwargs->used == 0) {
// Get config value
if (n_args != 2) {
mp_raise_TypeError(MP_ERROR_TEXT("must query one param"));
}
switch (mp_obj_str_get_qstr(args[1])) {
case MP_QSTR_dhcp4: {
return mp_obj_new_bool(network_ninaw10_dhcp_active);
}
case MP_QSTR_has_dhcp4: {
uint16_t ip_sum =
ifconfig.ip_addr[0] + ifconfig.ip_addr[1] + ifconfig.ip_addr[2] + ifconfig.ip_addr[3];
if (network_ninaw10_dhcp_active) {
return mp_obj_new_bool(ip_sum != 0);
} else {
return mp_const_false;
}
}
case MP_QSTR_addr4: {
mp_obj_t tuple[2] = {
netutils_format_ipv4_addr(ifconfig.ip_addr, NETUTILS_BIG),
netutils_format_ipv4_addr(ifconfig.subnet_addr, NETUTILS_BIG),
};
return mp_obj_new_tuple(2, tuple);
}
case MP_QSTR_gw4: {
return netutils_format_ipv4_addr(ifconfig.gateway_addr, NETUTILS_BIG);
}
default: {
mp_raise_ValueError(MP_ERROR_TEXT("unexpected key"));
break;
}
}
return mp_const_none;
} else {
// Set config value(s)
if (n_args != 1) {
mp_raise_TypeError(MP_ERROR_TEXT("can't specify pos and kw args"));
}
for (size_t i = 0; i < kwargs->alloc; ++i) {
if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) {
mp_map_elem_t *e = &kwargs->table[i];
switch (mp_obj_str_get_qstr(e->key)) {
case MP_QSTR_dhcp4: {
mp_raise_ValueError(MP_ERROR_TEXT("DHCP control unsupported"));
break;
}
case MP_QSTR_addr4: {
int prefix_bits = 32;
if (e->value != mp_const_none && mp_obj_is_str(e->value)) {
size_t addr_len;
const char *input_str = mp_obj_str_get_data(e->value, &addr_len);
char *split = strchr(input_str, '/');
if (split) {
mp_obj_t prefix_obj = mp_parse_num_integer(split + 1, strlen(split + 1), 10, NULL);
prefix_bits = mp_obj_get_int(prefix_obj);
uint32_t mask = -(1u << (32 - prefix_bits));
ifconfig.subnet_addr[0] = (mask >> 24) & 0xFF;
ifconfig.subnet_addr[1] = (mask >> 16) & 0xFF;
ifconfig.subnet_addr[2] = (mask >> 8) & 0xFF;
ifconfig.subnet_addr[3] = mask & 0xFF;
}
netutils_parse_ipv4_addr(e->value, ifconfig.ip_addr, NETUTILS_BIG);
} else if (e->value != mp_const_none) {
mp_obj_t *items;
mp_obj_get_array_fixed_n(e->value, 2, &items);
netutils_parse_ipv4_addr(items[0], ifconfig.ip_addr, NETUTILS_BIG);
netutils_parse_ipv4_addr(items[1], ifconfig.subnet_addr, NETUTILS_BIG);
}
nina_ifconfig(&ifconfig, true);
network_ninaw10_dhcp_active = false;
break;
}
case MP_QSTR_gw4: {
netutils_parse_ipv4_addr(e->value, ifconfig.gateway_addr, NETUTILS_BIG);
nina_ifconfig(&ifconfig, true);
network_ninaw10_dhcp_active = false;
break;
}
default: {
mp_raise_ValueError(MP_ERROR_TEXT("unexpected key"));
break;
}
}
}
}
}
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_KW(network_ninaw10_nic_ipconfig_obj, 1, network_ninaw10_nic_ipconfig);
static mp_obj_t network_ninaw10_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { static mp_obj_t network_ninaw10_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
nina_obj_t *self = MP_OBJ_TO_PTR(args[0]); nina_obj_t *self = MP_OBJ_TO_PTR(args[0]);
(void)self; (void)self;
@@ -524,7 +386,7 @@ static mp_obj_t network_ninaw10_config(size_t n_args, const mp_obj_t *args, mp_m
case MP_QSTR_ssid: { case MP_QSTR_ssid: {
nina_netinfo_t netinfo; nina_netinfo_t netinfo;
nina_netinfo(&netinfo); nina_netinfo(&netinfo);
return mp_obj_new_str_from_cstr(netinfo.ssid); return mp_obj_new_str(netinfo.ssid, strlen(netinfo.ssid));
} }
case MP_QSTR_security: { case MP_QSTR_security: {
nina_netinfo_t netinfo; nina_netinfo_t netinfo;
@@ -994,7 +856,6 @@ static const mp_rom_map_elem_t nina_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&network_ninaw10_disconnect_obj) }, { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&network_ninaw10_disconnect_obj) },
{ MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&network_ninaw10_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&network_ninaw10_isconnected_obj) },
{ MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_ninaw10_ifconfig_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_ninaw10_ifconfig_obj) },
{ MP_ROM_QSTR(MP_QSTR_ipconfig), MP_ROM_PTR(&network_ninaw10_nic_ipconfig_obj) },
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_ninaw10_config_obj) }, { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_ninaw10_config_obj) },
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_ninaw10_status_obj) }, { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_ninaw10_status_obj) },
{ MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&network_ninaw10_ioctl_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&network_ninaw10_ioctl_obj) },

View File

@@ -1,326 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2024 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "py/mphal.h"
#include "py/stream.h"
#include "extmod/modnetwork.h"
#if MICROPY_PY_NETWORK_PPP_LWIP
#include "lwip/dns.h"
#include "netif/ppp/ppp.h"
#include "netif/ppp/pppapi.h"
#include "netif/ppp/pppos.h"
// Enable this to see the serial data going between the PPP layer.
#define PPP_TRACE_IN_OUT (0)
typedef enum {
STATE_INACTIVE,
STATE_ACTIVE,
STATE_ERROR,
STATE_CONNECTING,
STATE_CONNECTED,
} network_ppp_state_t;
typedef struct _network_ppp_obj_t {
mp_obj_base_t base;
network_ppp_state_t state;
int error_code;
mp_obj_t stream;
ppp_pcb *pcb;
struct netif netif;
} network_ppp_obj_t;
const mp_obj_type_t mp_network_ppp_lwip_type;
static mp_obj_t network_ppp___del__(mp_obj_t self_in);
static void network_ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) {
network_ppp_obj_t *self = ctx;
switch (err_code) {
case PPPERR_NONE:
self->state = STATE_CONNECTED;
break;
case PPPERR_USER:
if (self->state >= STATE_ERROR) {
// Disable UART IRQ.
mp_obj_t dest[3];
mp_load_method(self->stream, MP_QSTR_irq, dest);
dest[2] = mp_const_none;
mp_call_method_n_kw(1, 0, dest);
// Indicate that the IRQ is disabled.
self->state = STATE_ACTIVE;
}
// Clean up the PPP PCB.
network_ppp___del__(MP_OBJ_FROM_PTR(self));
break;
default:
self->state = STATE_ERROR;
self->error_code = err_code;
break;
}
}
static mp_obj_t network_ppp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
mp_arg_check_num(n_args, n_kw, 1, 1, false);
mp_obj_t stream = all_args[0];
mp_get_stream_raise(stream, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE);
network_ppp_obj_t *self = mp_obj_malloc_with_finaliser(network_ppp_obj_t, type);
self->state = STATE_INACTIVE;
self->stream = stream;
self->pcb = NULL;
return MP_OBJ_FROM_PTR(self);
}
static mp_obj_t network_ppp___del__(mp_obj_t self_in) {
network_ppp_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->state >= STATE_ACTIVE) {
if (self->state >= STATE_ERROR) {
// Still connected over the UART stream.
// Force the connection to close, with nocarrier=1.
self->state = STATE_INACTIVE;
ppp_close(self->pcb, 1);
}
// Free PPP PCB and reset state.
self->state = STATE_INACTIVE;
ppp_free(self->pcb);
self->pcb = NULL;
}
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(network_ppp___del___obj, network_ppp___del__);
static mp_obj_t network_ppp_poll(size_t n_args, const mp_obj_t *args) {
network_ppp_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (self->state <= STATE_ERROR) {
return MP_OBJ_NEW_SMALL_INT(-MP_EPERM);
}
mp_int_t total_len = 0;
for (;;) {
uint8_t buf[256];
int err;
mp_uint_t len = mp_stream_rw(self->stream, buf, sizeof(buf), &err, 0);
if (len == 0) {
break;
}
#if PPP_TRACE_IN_OUT
mp_printf(&mp_plat_print, "ppp_in(n=%u,data=", len);
for (size_t i = 0; i < len; ++i) {
mp_printf(&mp_plat_print, "%02x:", buf[i]);
}
mp_printf(&mp_plat_print, ")\n");
#endif
pppos_input(self->pcb, (u8_t *)buf, len);
total_len += len;
}
return MP_OBJ_NEW_SMALL_INT(total_len);
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_ppp_poll_obj, 1, 2, network_ppp_poll);
static mp_obj_t network_ppp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
if (n_args != 1 && kwargs->used != 0) {
mp_raise_TypeError(MP_ERROR_TEXT("either pos or kw args are allowed"));
}
// network_ppp_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (kwargs->used != 0) {
for (size_t i = 0; i < kwargs->alloc; i++) {
if (mp_map_slot_is_filled(kwargs, i)) {
switch (mp_obj_str_get_qstr(kwargs->table[i].key)) {
default:
break;
}
}
}
return mp_const_none;
}
if (n_args != 2) {
mp_raise_TypeError(MP_ERROR_TEXT("can query only one param"));
}
mp_obj_t val = mp_const_none;
switch (mp_obj_str_get_qstr(args[1])) {
default:
mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
}
return val;
}
static MP_DEFINE_CONST_FUN_OBJ_KW(network_ppp_config_obj, 1, network_ppp_config);
static mp_obj_t network_ppp_status(mp_obj_t self_in) {
network_ppp_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->state == STATE_ERROR) {
return MP_OBJ_NEW_SMALL_INT(-self->error_code);
} else {
return MP_OBJ_NEW_SMALL_INT(self->state);
}
}
static MP_DEFINE_CONST_FUN_OBJ_1(network_ppp_status_obj, network_ppp_status);
static u32_t network_ppp_output_callback(ppp_pcb *pcb, const void *data, u32_t len, void *ctx) {
network_ppp_obj_t *self = ctx;
#if PPP_TRACE_IN_OUT
mp_printf(&mp_plat_print, "ppp_out(n=%u,data=", len);
for (size_t i = 0; i < len; ++i) {
mp_printf(&mp_plat_print, "%02x:", ((const uint8_t *)data)[i]);
}
mp_printf(&mp_plat_print, ")\n");
#endif
int err;
// The return value from this output callback is the number of bytes written out.
// If it's less than the requested number of bytes then lwIP will propagate out an error.
return mp_stream_rw(self->stream, (void *)data, len, &err, MP_STREAM_RW_WRITE);
}
static mp_obj_t network_ppp_connect(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
enum { ARG_security, ARG_user, ARG_key };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PPPAUTHTYPE_NONE} },
{ MP_QSTR_user, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
};
mp_arg_val_t parsed_args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, parsed_args);
network_ppp_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (self->state == STATE_INACTIVE) {
self->pcb = pppos_create(&self->netif, network_ppp_output_callback, network_ppp_status_cb, self);
if (self->pcb == NULL) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("pppos_create failed"));
}
self->state = STATE_ACTIVE;
// Enable UART IRQ to call PPP.poll() when incoming data is ready.
mp_obj_t dest[4];
mp_load_method(self->stream, MP_QSTR_irq, dest);
dest[2] = mp_obj_new_bound_meth(MP_OBJ_FROM_PTR(&network_ppp_poll_obj), MP_OBJ_FROM_PTR(self));
dest[3] = mp_load_attr(self->stream, MP_QSTR_IRQ_RXIDLE);
mp_call_method_n_kw(2, 0, dest);
}
if (self->state == STATE_CONNECTING || self->state == STATE_CONNECTED) {
mp_raise_OSError(MP_EALREADY);
}
switch (parsed_args[ARG_security].u_int) {
case PPPAUTHTYPE_NONE:
case PPPAUTHTYPE_PAP:
case PPPAUTHTYPE_CHAP:
break;
default:
mp_raise_ValueError(MP_ERROR_TEXT("invalid auth"));
}
if (parsed_args[ARG_security].u_int != PPPAUTHTYPE_NONE) {
const char *user_str = mp_obj_str_get_str(parsed_args[ARG_user].u_obj);
const char *key_str = mp_obj_str_get_str(parsed_args[ARG_key].u_obj);
ppp_set_auth(self->pcb, parsed_args[ARG_security].u_int, user_str, key_str);
}
netif_set_default(self->pcb->netif);
ppp_set_usepeerdns(self->pcb, true);
if (ppp_connect(self->pcb, 0) != ERR_OK) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("ppp_connect failed"));
}
self->state = STATE_CONNECTING;
// Do a poll in case there is data waiting on the input stream.
network_ppp_poll(1, args);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_KW(network_ppp_connect_obj, 1, network_ppp_connect);
static mp_obj_t network_ppp_disconnect(mp_obj_t self_in) {
network_ppp_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->state == STATE_CONNECTING || self->state == STATE_CONNECTED) {
// Initiate close and wait for PPPERR_USER callback.
ppp_close(self->pcb, 0);
}
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(network_ppp_disconnect_obj, network_ppp_disconnect);
static mp_obj_t network_ppp_isconnected(mp_obj_t self_in) {
network_ppp_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_bool(self->state == STATE_CONNECTED);
}
static MP_DEFINE_CONST_FUN_OBJ_1(network_ppp_isconnected_obj, network_ppp_isconnected);
static mp_obj_t network_ppp_ifconfig(size_t n_args, const mp_obj_t *args) {
network_ppp_obj_t *self = MP_OBJ_TO_PTR(args[0]);
return mod_network_nic_ifconfig(&self->netif, n_args - 1, args + 1);
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_ppp_ifconfig_obj, 1, 2, network_ppp_ifconfig);
static mp_obj_t network_ppp_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
network_ppp_obj_t *self = MP_OBJ_TO_PTR(args[0]);
return mod_network_nic_ipconfig(&self->netif, n_args - 1, args + 1, kwargs);
}
static MP_DEFINE_CONST_FUN_OBJ_KW(network_ppp_ipconfig_obj, 1, network_ppp_ipconfig);
static const mp_rom_map_elem_t network_ppp_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&network_ppp___del___obj) },
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_ppp_config_obj) },
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_ppp_status_obj) },
{ MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&network_ppp_connect_obj) },
{ MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&network_ppp_disconnect_obj) },
{ MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&network_ppp_isconnected_obj) },
{ MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_ppp_ifconfig_obj) },
{ MP_ROM_QSTR(MP_QSTR_ipconfig), MP_ROM_PTR(&network_ppp_ipconfig_obj) },
{ MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&network_ppp_poll_obj) },
{ MP_ROM_QSTR(MP_QSTR_SEC_NONE), MP_ROM_INT(PPPAUTHTYPE_NONE) },
{ MP_ROM_QSTR(MP_QSTR_SEC_PAP), MP_ROM_INT(PPPAUTHTYPE_PAP) },
{ MP_ROM_QSTR(MP_QSTR_SEC_CHAP), MP_ROM_INT(PPPAUTHTYPE_CHAP) },
};
static MP_DEFINE_CONST_DICT(network_ppp_locals_dict, network_ppp_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(
mp_network_ppp_lwip_type,
MP_QSTR_PPP,
MP_TYPE_FLAG_NONE,
make_new, network_ppp_make_new,
locals_dict, &network_ppp_locals_dict
);
#endif

View File

@@ -58,11 +58,9 @@
#include "shared/netutils/netutils.h" #include "shared/netutils/netutils.h"
#include "lib/wiznet5k/Ethernet/wizchip_conf.h" #include "lib/wiznet5k/Ethernet/wizchip_conf.h"
#include "lib/wiznet5k/Ethernet/socket.h" #include "lib/wiznet5k/Ethernet/socket.h"
#include "lwip/apps/mdns.h"
#include "lwip/err.h" #include "lwip/err.h"
#include "lwip/dns.h" #include "lwip/dns.h"
#include "lwip/dhcp.h" #include "lwip/dhcp.h"
#include "lwip/ethip6.h"
#include "netif/etharp.h" #include "netif/etharp.h"
#define TRACE_ETH_TX (0x0002) #define TRACE_ETH_TX (0x0002)
@@ -202,9 +200,6 @@ static void wiznet5k_config_interrupt(bool enabled) {
void wiznet5k_deinit(void) { void wiznet5k_deinit(void) {
for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) {
if (netif == &wiznet5k_obj.netif) { if (netif == &wiznet5k_obj.netif) {
#if LWIP_MDNS_RESPONDER
mdns_resp_remove_netif(&wiznet5k_obj.netif);
#endif
netif_remove(netif); netif_remove(netif);
netif->flags = 0; netif->flags = 0;
break; break;
@@ -302,21 +297,13 @@ static err_t wiznet5k_netif_init(struct netif *netif) {
netif->hwaddr_len = sizeof(netif->hwaddr); netif->hwaddr_len = sizeof(netif->hwaddr);
int ret = WIZCHIP_EXPORT(socket)(0, Sn_MR_MACRAW, 0, 0); int ret = WIZCHIP_EXPORT(socket)(0, Sn_MR_MACRAW, 0, 0);
if (ret != 0) { if (ret != 0) {
printf("WIZNET fatal error in netif_init: %d\n", ret); printf("WIZNET fatal error in netifinit: %d\n", ret);
return ERR_IF; return ERR_IF;
} }
// Enable MAC filtering so we only get frames destined for us, to reduce load on lwIP // Enable MAC filtering so we only get frames destined for us, to reduce load on lwIP
setSn_MR(0, getSn_MR(0) | Sn_MR_MFEN); setSn_MR(0, getSn_MR(0) | Sn_MR_MFEN);
#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
netif->flags |= NETIF_FLAG_MLD6;
#else
// Drop IPv6 packets if firmware does not support it
setSn_MR(0, getSn_MR(0) | Sn_MR_MIP6B);
#endif
return ERR_OK; return ERR_OK;
} }
@@ -338,12 +325,6 @@ static void wiznet5k_lwip_init(wiznet5k_obj_t *self) {
self->netif.flags |= NETIF_FLAG_UP; self->netif.flags |= NETIF_FLAG_UP;
dhcp_start(&self->netif); dhcp_start(&self->netif);
self->netif.flags &= ~NETIF_FLAG_UP; self->netif.flags &= ~NETIF_FLAG_UP;
#if LWIP_MDNS_RESPONDER
// NOTE: interface is removed in ::wiznet5k_deinit(), which is called as
// part of the init sequence.
mdns_resp_add_netif(&self->netif, mod_network_hostname_data);
#endif
} }
void wiznet5k_poll(void) { void wiznet5k_poll(void) {
@@ -866,10 +847,6 @@ static mp_obj_t wiznet5k_active(size_t n_args, const mp_obj_t *args) {
setSHAR(mac); setSHAR(mac);
} }
#if WIZNET5K_WITH_LWIP_STACK && LWIP_IPV6
netif_create_ip6_linklocal_address(&self->netif, 1);
#endif
// seems we need a small delay after init // seems we need a small delay after init
mp_hal_delay_ms(250); mp_hal_delay_ms(250);

View File

@@ -139,7 +139,7 @@ mp_import_stat_t mp_vfs_import_stat(const char *path) {
} }
// delegate to vfs.stat() method // delegate to vfs.stat() method
mp_obj_t path_o = mp_obj_new_str_from_cstr(path_out); mp_obj_t path_o = mp_obj_new_str(path_out, strlen(path_out));
mp_obj_t stat; mp_obj_t stat;
nlr_buf_t nlr; nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) { if (nlr_push(&nlr) == 0) {
@@ -273,7 +273,7 @@ mp_obj_t mp_vfs_umount(mp_obj_t mnt_in) {
mnt_str = mp_obj_str_get_data(mnt_in, &mnt_len); mnt_str = mp_obj_str_get_data(mnt_in, &mnt_len);
} }
for (mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table); *vfsp != NULL; vfsp = &(*vfsp)->next) { for (mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table); *vfsp != NULL; vfsp = &(*vfsp)->next) {
if ((mnt_str != NULL && mnt_len == (*vfsp)->len && !memcmp(mnt_str, (*vfsp)->str, mnt_len)) || (*vfsp)->obj == mnt_in) { if ((mnt_str != NULL && !memcmp(mnt_str, (*vfsp)->str, mnt_len + 1)) || (*vfsp)->obj == mnt_in) {
vfs = *vfsp; vfs = *vfsp;
*vfsp = (*vfsp)->next; *vfsp = (*vfsp)->next;
break; break;

View File

@@ -46,45 +46,31 @@ void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) {
} }
} }
// Helper function to minimise code size of read/write functions
// note the n_args argument is moved to the end for further code size reduction (args keep same position in caller and callee).
static int mp_vfs_blockdev_call_rw(mp_obj_t *args, size_t block_num, size_t block_off, size_t len, void *buf, size_t n_args) {
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, buf};
args[2] = MP_OBJ_NEW_SMALL_INT(block_num);
args[3] = MP_OBJ_FROM_PTR(&ar);
args[4] = MP_OBJ_NEW_SMALL_INT(block_off); // ignored for n_args == 2
mp_obj_t ret = mp_call_method_n_kw(n_args, 0, args);
if (ret == mp_const_none) {
return 0;
} else {
// Some block devices return a bool indicating success, so
// convert those to an errno integer code.
if (ret == mp_const_true) {
return 0;
} else if (ret == mp_const_false) {
return -MP_EIO;
}
// Block device functions are expected to return 0 on success
// and negative integer on errors. Check for positive integer
// results as some callers (i.e. littlefs) will produce corrupt
// results from these.
int i = MP_OBJ_SMALL_INT_VALUE(ret);
return i > 0 ? (-MP_EINVAL) : i;
}
}
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]; mp_uint_t (*f)(uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->readblocks[2];
return f(buf, block_num, num_blocks); return f(buf, block_num, num_blocks);
} else { } else {
return mp_vfs_blockdev_call_rw(self->readblocks, block_num, 0, num_blocks * self->block_size, buf, 2); 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[3] = MP_OBJ_FROM_PTR(&ar);
mp_call_method_n_kw(2, 0, self->readblocks);
// TODO handle error return
return 0;
} }
} }
int mp_vfs_blockdev_read_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, uint8_t *buf) { int mp_vfs_blockdev_read_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, uint8_t *buf) {
return mp_vfs_blockdev_call_rw(self->readblocks, block_num, block_off, len, buf, 3); mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, buf};
self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
self->readblocks[3] = MP_OBJ_FROM_PTR(&ar);
self->readblocks[4] = MP_OBJ_NEW_SMALL_INT(block_off);
mp_obj_t ret = mp_call_method_n_kw(3, 0, self->readblocks);
if (ret == mp_const_none) {
return 0;
} else {
return MP_OBJ_SMALL_INT_VALUE(ret);
}
} }
int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, const uint8_t *buf) { int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, const uint8_t *buf) {
@@ -97,7 +83,12 @@ int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_
mp_uint_t (*f)(const uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->writeblocks[2]; mp_uint_t (*f)(const uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->writeblocks[2];
return f(buf, block_num, num_blocks); return f(buf, block_num, num_blocks);
} else { } else {
return mp_vfs_blockdev_call_rw(self->writeblocks, block_num, 0, num_blocks * self->block_size, (void *)buf, 2); 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[3] = MP_OBJ_FROM_PTR(&ar);
mp_call_method_n_kw(2, 0, self->writeblocks);
// TODO handle error return
return 0;
} }
} }
@@ -106,7 +97,17 @@ int mp_vfs_blockdev_write_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t
// read-only block device // read-only block device
return -MP_EROFS; return -MP_EROFS;
} }
return mp_vfs_blockdev_call_rw(self->writeblocks, block_num, block_off, len, (void *)buf, 3);
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, (void *)buf};
self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
self->writeblocks[3] = MP_OBJ_FROM_PTR(&ar);
self->writeblocks[4] = MP_OBJ_NEW_SMALL_INT(block_off);
mp_obj_t ret = mp_call_method_n_kw(3, 0, self->writeblocks);
if (ret == mp_const_none) {
return 0;
} else {
return MP_OBJ_SMALL_INT_VALUE(ret);
}
} }
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) {

View File

@@ -114,11 +114,6 @@ static mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) {
mp_raise_OSError(fresult_to_errno_table[res]); mp_raise_OSError(fresult_to_errno_table[res]);
} }
// set the filesystem label if it's configured
#ifdef MICROPY_HW_FLASH_FS_LABEL
f_setlabel(&vfs->fatfs, MICROPY_HW_FLASH_FS_LABEL);
#endif
return mp_const_none; return mp_const_none;
} }
static MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_mkfs_fun_obj, fat_vfs_mkfs); static MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_mkfs_fun_obj, fat_vfs_mkfs);
@@ -149,7 +144,7 @@ static mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) {
// make 4-tuple with info about this entry // make 4-tuple with info about this entry
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL)); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL));
if (self->is_str) { if (self->is_str) {
t->items[0] = mp_obj_new_str_from_cstr(fn); t->items[0] = mp_obj_new_str(fn, strlen(fn));
} else { } else {
t->items[0] = mp_obj_new_bytes((const byte *)fn, strlen(fn)); t->items[0] = mp_obj_new_bytes((const byte *)fn, strlen(fn));
} }
@@ -296,7 +291,7 @@ static mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) {
if (res != FR_OK) { if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]); mp_raise_OSError(fresult_to_errno_table[res]);
} }
return mp_obj_new_str_from_cstr(buf); return mp_obj_new_str(buf, strlen(buf));
} }
static MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd); static MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd);

View File

@@ -192,7 +192,7 @@ static mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) {
// make 4-tuple with info about this entry // make 4-tuple with info about this entry
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL)); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL));
if (self->is_str) { if (self->is_str) {
t->items[0] = mp_obj_new_str_from_cstr(info.name); t->items[0] = mp_obj_new_str(info.name, strlen(info.name));
} else { } else {
t->items[0] = mp_obj_new_bytes((const byte *)info.name, strlen(info.name)); t->items[0] = mp_obj_new_bytes((const byte *)info.name, strlen(info.name));
} }

View File

@@ -194,7 +194,7 @@ static mp_obj_t vfs_posix_getcwd(mp_obj_t self_in) {
} }
#endif #endif
} }
return mp_obj_new_str_from_cstr(ret); return mp_obj_new_str(ret, strlen(ret));
} }
static MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_getcwd_obj, vfs_posix_getcwd); static MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_getcwd_obj, vfs_posix_getcwd);
@@ -234,7 +234,7 @@ static mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) {
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL));
if (self->is_str) { if (self->is_str) {
t->items[0] = mp_obj_new_str_from_cstr(fn); t->items[0] = mp_obj_new_str(fn, strlen(fn));
} else { } else {
t->items[0] = mp_obj_new_bytes((const byte *)fn, strlen(fn)); t->items[0] = mp_obj_new_bytes((const byte *)fn, strlen(fn));
} }

View File

@@ -160,27 +160,12 @@ static mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_
#if defined(__APPLE__) #if defined(__APPLE__)
#define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == ENOTSUP) #define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == ENOTSUP)
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
// In debug builds fsync (i.e. _commit on windows) will generate a debug report via _ASSERTE when
// called with non-redirected stdin/stdout/stderr (i.e. _isatty) handles because FlushFileBuffers,
// which it calls internally, will fail since console output is not buffered.
// In release builds it also fails, but merely returns an error which is handled appropriately below.
// The check for the handle being stdin/stdout/stderr is added explicitly because according to
// the documentation _isatty is also true for serial ports for instance.
#ifdef _DEBUG
if ((o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO) && _isatty(o->fd)) {
return 0;
}
#endif
#define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == EBADF) #define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == EBADF)
#else #else
#define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL) #define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL)
#endif #endif
MP_HAL_RETRY_SYSCALL(ret, fsync(o->fd), { MP_HAL_RETRY_SYSCALL(ret, fsync(o->fd), {
if (VFS_POSIX_STREAM_STDIO_ERR_CATCH if (VFS_POSIX_STREAM_STDIO_ERR_CATCH
// Note: comparing fd against the standard FILENOs is technically not correct, for example:
// sys.stderr.close() in Python code results in close(STDERR_FILENO) here, but because
// open() uses the next available file descriptor, opening an arbitrary file with
// fd = open('/some/file') means that fd becomes STDERR_FILENO.
&& (o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO)) { && (o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO)) {
return 0; return 0;
} }

View File

@@ -19,10 +19,7 @@
#include <stdint.h> #include <stdint.h>
#include <math.h> #include <math.h>
// These lines verify that FLT_EVAL_METHOD==0, MicroPython's libm requires this. #define FLT_EVAL_METHOD 0
// If compilation fails here then check the host compiler's FLT_EVAL_METHOD.
typedef float float_t;
typedef double double_t;
#define FORCE_EVAL(x) do { \ #define FORCE_EVAL(x) do { \
if (sizeof(x) == sizeof(float)) { \ if (sizeof(x) == sizeof(float)) { \

View File

@@ -24,9 +24,7 @@
*/ */
#include "fdlibm.h" #include "fdlibm.h"
#ifndef _IEEE_LIBM
#define _IEEE_LIBM 1 #define _IEEE_LIBM 1
#endif
#ifdef __STDC__ #ifdef __STDC__
float lgammaf(float x) float lgammaf(float x)

View File

@@ -24,9 +24,7 @@
#include "math.h" #include "math.h"
#include "fdlibm.h" #include "fdlibm.h"
#ifndef _IEEE_LIBM
#define _IEEE_LIBM 1 #define _IEEE_LIBM 1
#endif
#ifdef __STDC__ #ifdef __STDC__
float tgammaf(float x) float tgammaf(float x)

View File

@@ -15,10 +15,7 @@
#include <stdint.h> #include <stdint.h>
#include <math.h> #include <math.h>
// These lines verify that FLT_EVAL_METHOD==0, MicroPython's libm requires this. #define FLT_EVAL_METHOD 0
// If compilation fails here then check the host compiler's FLT_EVAL_METHOD.
typedef float float_t;
typedef double double_t;
#define FORCE_EVAL(x) do { \ #define FORCE_EVAL(x) do { \
if (sizeof(x) == sizeof(float)) { \ if (sizeof(x) == sizeof(float)) { \

18
lib/tinytest/README Normal file
View File

@@ -0,0 +1,18 @@
Tinytest is a tiny little test framework written in C by Nick Mathewson.
It is distributed under the 3-clause BSD license. You can use it in
your own programs so long as you follow the license's conditions.
It's been tested on Windows, Mac, and many of the free Unixes.
It knows how to fork before running certain tests, and it makes
text-mode output in a format I like.
For info on how to use it, check out tinytest_demo.c.
You can get the latest version using Git, by pulling from
git://github.com/nmathewson/tinytest.git
Patches are welcome. Patches that turn this from tinytest to hugetest
will not be applied. If you want a huge test framework, use CUnit.

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