diff --git a/.github/workflows/ports_alif.yml b/.github/workflows/ports_alif.yml new file mode 100644 index 0000000000000..0e96e7d816e50 --- /dev/null +++ b/.github/workflows/ports_alif.yml @@ -0,0 +1,33 @@ +name: alif port + +on: + push: + pull_request: + paths: + - '.github/workflows/*.yml' + - 'tools/**' + - 'py/**' + - 'extmod/**' + - 'shared/**' + - 'lib/**' + - 'drivers/**' + - 'ports/alif/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build_alif: + strategy: + fail-fast: false + matrix: + ci_func: # names are functions in ci.sh + - alif_ae3_build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install packages + run: source tools/ci.sh && ci_alif_setup + - name: Build ci_${{matrix.ci_func }} + run: source tools/ci.sh && ci_${{ matrix.ci_func }} diff --git a/.github/workflows/ports_qemu.yml b/.github/workflows/ports_qemu.yml index 57192c43936e5..ac09dde86408b 100644 --- a/.github/workflows/ports_qemu.yml +++ b/.github/workflows/ports_qemu.yml @@ -20,13 +20,20 @@ concurrency: jobs: build_and_test_arm: + strategy: + fail-fast: false + matrix: + ci_func: # names are functions in ci.sh + - bigendian + - sabrelite + - thumb 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: Build and run test suite ci_qemu_build_arm_${{ matrix.ci_func }} + run: source tools/ci.sh && ci_qemu_build_arm_${{ matrix.ci_func }} - name: Print failures if: failure() run: tests/run-tests.py --print-failures diff --git a/.github/workflows/ports_unix.yml b/.github/workflows/ports_unix.yml index 2547015038e4d..f3f613a789af3 100644 --- a/.github/workflows/ports_unix.yml +++ b/.github/workflows/ports_unix.yml @@ -71,6 +71,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + # Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests. + # Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default. + with: + python-version: '3.11' - name: Install packages run: source tools/ci.sh && ci_unix_coverage_setup - name: Build @@ -129,6 +134,20 @@ jobs: if: failure() run: tests/run-tests.py --print-failures + longlong: + runs-on: ubuntu-22.04 # use 22.04 to get python2, and libffi-dev:i386 + steps: + - uses: actions/checkout@v4 + - name: Install packages + run: source tools/ci.sh && ci_unix_32bit_setup + - name: Build + run: source tools/ci.sh && ci_unix_longlong_build + - name: Run main test suite + run: source tools/ci.sh && ci_unix_longlong_run_tests + - name: Print failures + if: failure() + run: tests/run-tests.py --print-failures + float: runs-on: ubuntu-latest steps: @@ -141,47 +160,42 @@ jobs: if: failure() run: tests/run-tests.py --print-failures - stackless_clang: + gil_enabled: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Install packages - run: source tools/ci.sh && ci_unix_clang_setup - name: Build - run: source tools/ci.sh && ci_unix_stackless_clang_build + run: source tools/ci.sh && ci_unix_gil_enabled_build - name: Run main test suite - run: source tools/ci.sh && ci_unix_stackless_clang_run_tests + run: source tools/ci.sh && ci_unix_gil_enabled_run_tests - name: Print failures if: failure() run: tests/run-tests.py --print-failures - float_clang: + stackless_clang: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_clang_setup - name: Build - run: source tools/ci.sh && ci_unix_float_clang_build + run: source tools/ci.sh && ci_unix_stackless_clang_build - name: Run main test suite - run: source tools/ci.sh && ci_unix_float_clang_run_tests + run: source tools/ci.sh && ci_unix_stackless_clang_run_tests - name: Print failures if: failure() run: tests/run-tests.py --print-failures - settrace: + float_clang: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - # Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests. - # Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default. - with: - python-version: '3.11' + - name: Install packages + run: source tools/ci.sh && ci_unix_clang_setup - name: Build - run: source tools/ci.sh && ci_unix_settrace_build + run: source tools/ci.sh && ci_unix_float_clang_build - name: Run main test suite - run: source tools/ci.sh && ci_unix_settrace_run_tests + run: source tools/ci.sh && ci_unix_float_clang_run_tests - name: Print failures if: failure() run: tests/run-tests.py --print-failures @@ -262,3 +276,53 @@ jobs: - name: Print failures if: failure() run: tests/run-tests.py --print-failures + + sanitize_address: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + # Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests. + # Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default. + with: + python-version: '3.11' + - name: Install packages + run: source tools/ci.sh && ci_unix_coverage_setup + - name: Build + run: source tools/ci.sh && ci_unix_sanitize_address_build + - name: Run main test suite + run: source tools/ci.sh && ci_unix_sanitize_address_run_tests + - name: Test merging .mpy files + run: source tools/ci.sh && ci_unix_coverage_run_mpy_merge_tests + - name: Build native mpy modules + run: source tools/ci.sh && ci_native_mpy_modules_build + - name: Test importing .mpy generated by mpy_ld.py + run: source tools/ci.sh && ci_unix_coverage_run_native_mpy_tests + - name: Print failures + if: failure() + run: tests/run-tests.py --print-failures + + sanitize_undefined: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + # Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests. + # Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default. + with: + python-version: '3.11' + - name: Install packages + run: source tools/ci.sh && ci_unix_coverage_setup + - name: Build + run: source tools/ci.sh && ci_unix_sanitize_undefined_build + - name: Run main test suite + run: source tools/ci.sh && ci_unix_sanitize_undefined_run_tests + - name: Test merging .mpy files + run: source tools/ci.sh && ci_unix_coverage_run_mpy_merge_tests + - name: Build native mpy modules + run: source tools/ci.sh && ci_native_mpy_modules_build + - name: Test importing .mpy generated by mpy_ld.py + run: source tools/ci.sh && ci_unix_coverage_run_native_mpy_tests + - name: Print failures + if: failure() + run: tests/run-tests.py --print-failures diff --git a/.github/workflows/ports_windows.yml b/.github/workflows/ports_windows.yml index 84e018ba15d16..f33277d471d3c 100644 --- a/.github/workflows/ports_windows.yml +++ b/.github/workflows/ports_windows.yml @@ -28,13 +28,10 @@ jobs: visualstudio: ['2017', '2019', '2022'] include: - visualstudio: '2017' - runner: windows-latest vs_version: '[15, 16)' - visualstudio: '2019' - runner: windows-2019 vs_version: '[16, 17)' - visualstudio: '2022' - runner: windows-2022 vs_version: '[17, 18)' # trim down the number of jobs in the matrix exclude: @@ -42,9 +39,9 @@ jobs: configuration: Debug - visualstudio: '2019' configuration: Debug + runs-on: windows-latest env: CI_BUILD_CONFIGURATION: ${{ matrix.configuration }} - runs-on: ${{ matrix.runner }} steps: - name: Install Visual Studio 2017 if: matrix.visualstudio == '2017' @@ -52,13 +49,15 @@ jobs: choco install visualstudio2017buildtools choco install visualstudio2017-workload-vctools choco install windows-sdk-8.1 + - name: Install Visual Studio 2019 + if: matrix.visualstudio == '2019' + run: | + choco install visualstudio2019buildtools + choco install visualstudio2019-workload-vctools + choco install windows-sdk-8.1 - uses: microsoft/setup-msbuild@v2 with: vs-version: ${{ matrix.vs_version }} - - uses: actions/setup-python@v5 - if: matrix.runner == 'windows-2019' - with: - python-version: '3.9' - uses: actions/checkout@v4 - name: Build mpy-cross.exe run: msbuild mpy-cross\mpy-cross.vcxproj -maxcpucount -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }} @@ -103,7 +102,7 @@ jobs: env: i686 - sys: mingw64 env: x86_64 - runs-on: windows-2022 + runs-on: windows-latest env: CHERE_INVOKING: enabled_from_arguments defaults: diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml index 9265c25bcba13..4c4a2a3162ed6 100644 --- a/.github/workflows/ruff.yml +++ b/.github/workflows/ruff.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - # ruff version should be kept in sync with .pre-commit-config.yaml - - run: pipx install ruff==0.9.6 + # ruff version should be kept in sync with .pre-commit-config.yaml & also micropython-lib + - run: pipx install ruff==0.11.6 - run: ruff check --output-format=github . - run: ruff format --diff . diff --git a/.gitmodules b/.gitmodules index 6338f0e66d63d..02849ec9bdd11 100644 --- a/.gitmodules +++ b/.gitmodules @@ -68,3 +68,9 @@ [submodule "lib/arduino-lib"] path = lib/arduino-lib url = https://github.com/arduino/arduino-lib-mpy.git +[submodule "lib/alif_ensemble-cmsis-dfp"] + path = lib/alif_ensemble-cmsis-dfp + url = https://github.com/alifsemi/alif_ensemble-cmsis-dfp.git +[submodule "lib/alif-security-toolkit"] + path = lib/alif-security-toolkit + url = https://github.com/micropython/alif-security-toolkit.git diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d07f9b0fda2a9..ac9785bb59232 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,8 +12,8 @@ repos: verbose: true stages: [commit-msg] - repo: https://github.com/charliermarsh/ruff-pre-commit - # Version should be kept in sync with .github/workflows/ruff.yml - rev: v0.9.6 + # Version should be kept in sync with .github/workflows/ruff.yml & also micropython-lib + rev: v0.11.6 hooks: - id: ruff - id: ruff-format diff --git a/CODECONVENTIONS.md b/CODECONVENTIONS.md index d6af0418e42ef..d3f71cb083deb 100644 --- a/CODECONVENTIONS.md +++ b/CODECONVENTIONS.md @@ -206,14 +206,21 @@ adhere to the existing style and use `tools/codeformat.py` to check any changes. The main conventions, and things not enforceable via the auto-formatter, are described below. -White space: +As the MicroPython code base is over ten years old, not every source file +conforms fully to these conventions. If making small changes to existing code, +then it's usually acceptable to follow the existing code's style. New code or +major changes should follow the conventions described here. + +## White space + - Expand tabs to 4 spaces. - Don't leave trailing whitespace at the end of a line. - For control blocks (if, for, while), put 1 space between the keyword and the opening parenthesis. - Put 1 space after a comma, and 1 space around operators. -Braces: +## Braces + - Use braces for all blocks, even no-line and single-line pieces of code. - Put opening braces on the end of the line it belongs to, not on @@ -221,18 +228,43 @@ Braces: - For else-statements, put the else on the same line as the previous closing brace. -Header files: +## Header files + - Header files should be protected from multiple inclusion with #if directives. See an existing header for naming convention. -Names: +## Names + - Use underscore_case, not camelCase for all names. - Use CAPS_WITH_UNDERSCORE for enums and macros. - When defining a type use underscore_case and put '_t' after it. -Integer types: MicroPython runs on 16, 32, and 64 bit machines, so it's -important to use the correctly-sized (and signed) integer types. The -general guidelines are: +### Public names (declared in headers) + +- MicroPython-specific names (especially any declared in `py/` and `extmod/` + directories) should generally start with `mp_` or `MP_`. +- Functions and variables declared in a header should generally share a longer + common prefix. Usually the prefix matches the file name (i.e. items defined in + `py/obj.c` are declared in `py/obj.h` and should be prefixed `mp_obj_`). There + are exceptions, for example where one header file contains declarations + implemented in multiple source files for expediency. + +### Private names (specific to a single .c file) + +- For static functions and variables exposed to Python (i.e. a static C function + that is wrapped in `MP_DEFINE_CONST_FUN_...` and attached to a module), use + the file-level shared common prefix, i.e. name them as if the function or + variable was not static. +- Other static definitions in source files (i.e. functions or variables defined + in a .c file that are only used within that .c file) don't need any prefix + (specifically: no `s_` or `_` prefix, and generally avoid adding the + file-level common prefix). + +## Integer types + +MicroPython runs on 16, 32, and 64 bit machines, so it's important to use the +correctly-sized (and signed) integer types. The general guidelines are: + - For most cases use mp_int_t for signed and mp_uint_t for unsigned integer values. These are guaranteed to be machine-word sized and therefore big enough to hold the value from a MicroPython small-int @@ -241,11 +273,13 @@ general guidelines are: - You can use int/uint, but remember that they may be 16-bits wide. - If in doubt, use mp_int_t/mp_uint_t. -Comments: +## Comments + - Be concise and only write comments for things that are not obvious. - Use `// ` prefix, NOT `/* ... */`. No extra fluff. -Memory allocation: +## Memory allocation + - Use m_new, m_renew, m_del (and friends) to allocate and free heap memory. These macros are defined in py/misc.h. diff --git a/docs/develop/natmod.rst b/docs/develop/natmod.rst index ba45e4305c66d..072d78b2076b4 100644 --- a/docs/develop/natmod.rst +++ b/docs/develop/natmod.rst @@ -67,14 +67,31 @@ The known limitations are: * static BSS variables are not supported; workaround: use global BSS variables +* thread-local storage variables are not supported on rv32imc; workaround: use + global BSS variables or allocate some space on the heap to store them + So, if your C code has writable data, make sure the data is defined globally, without an initialiser, and only written to within functions. +The native module is not automatically linked against the standard static libraries +like ``libm.a`` and ``libgcc.a``, which can lead to ``undefined symbol`` errors. +You can link the runtime libraries by setting ``LINK_RUNTIME = 1`` +in your Makefile. Custom static libraries can also be linked by adding +``MPY_LD_FLAGS += -l path/to/library.a``. Note that these are linked into +the native module and will not be shared with other modules or the system. + Linker limitation: the native module is not linked against the symbol table of the full MicroPython firmware. Rather, it is linked against an explicit table of exported symbols found in ``mp_fun_table`` (in ``py/nativeglue.h``), that is fixed at firmware build time. It is thus not possible to simply call some arbitrary HAL/OS/RTOS/system -function, for example. +function, for example, unless that resides at a fixed address. In that case, the path +of a linkerscript containing a series of symbol names and their fixed address can be +passed to ``mpy_ld.py`` via the ``--externs`` command line argument. That way symbols +appearing in the linkerscript will take precedence over what is provided from object +files, but at the moment the object files' implementation will still reside in the +final MPY file. The linkerscript parser is limited in its capabilities, and is +currently used only for parsing the ESP8266 port ROM symbols list (see +``ports/esp8266/boards/eagle.rom.addr.v6.ld``). New symbols can be added to the end of the table and the firmware rebuilt. The symbols also need to be added to ``tools/mpy_ld.py``'s ``fun_table`` dict in the @@ -211,6 +228,26 @@ other module, for example:: print(factorial.factorial(10)) # should display 3628800 +Using Picolibc when building modules +------------------------------------ + +Using `Picolibc `_ as your C standard +library is not only supported, but in fact it is the default for the rv32imc +platform. However, there are a couple of things worth mentioning to make sure +you don't run into problems later when building code. + +Some pre-built Picolibc versions (for example, those provided by Ubuntu Linux +as the ``picolibc-arm-none-eabi``, ``picolibc-riscv64-unknown-elf``, and +``picolibc-xtensa-lx106-elf`` packages) assume thread-local storage (TLS) is +available at runtime, but unfortunately MicroPython modules do not support that +on some architectures (namely ``rv32imc``). This means that some +functionalities provided by Picolibc will default to use TLS, returning an +error either during compilation or during linking. + +For an example on how this may affect you, the ``examples/natmod/btree`` +example module contains a workaround to make sure ``errno`` works (look for +``__PICOLIBC_ERRNO_FUNCTION`` in the Makefile and follow the trail from there). + Further examples ---------------- diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 0780e01300801..c394414a76f51 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -83,30 +83,30 @@ The :class:`network.WLAN` class in the :mod:`network` module:: import network - wlan = network.WLAN(network.WLAN.IF_STA) # create station interface - wlan.active(True) # activate the interface - wlan.scan() # scan for access points - wlan.isconnected() # check if the station is connected to an AP + wlan = network.WLAN() # create station interface (the default, see below for an access point interface) + wlan.active(True) # activate the interface + wlan.scan() # scan for access points + wlan.isconnected() # check if the station is connected to an AP wlan.connect('ssid', 'key') # connect to an AP - wlan.config('mac') # get the interface's MAC address - wlan.ipconfig('addr4') # get the interface's IPv4 addresses + wlan.config('mac') # get the interface's MAC address + wlan.ipconfig('addr4') # get the interface's IPv4 addresses ap = network.WLAN(network.WLAN.IF_AP) # create access-point interface - ap.config(ssid='ESP-AP') # set the SSID of the access point - ap.config(max_clients=10) # set how many clients can connect to the network - ap.active(True) # activate the interface + ap.config(ssid='ESP-AP') # set the SSID of the access point + ap.config(max_clients=10) # set how many clients can connect to the network + ap.active(True) # activate the interface A useful function for connecting to your local WiFi network is:: def do_connect(): - import network - wlan = network.WLAN(network.WLAN.IF_STA) + import machine, network + wlan = network.WLAN() wlan.active(True) if not wlan.isconnected(): print('connecting to network...') wlan.connect('ssid', 'key') while not wlan.isconnected(): - pass + machine.idle() print('network config:', wlan.ipconfig('addr4')) Once the network is established the :mod:`socket ` module can be used @@ -148,6 +148,7 @@ Required keyword arguments for the constructor: - ``mdc`` and ``mdio`` - :class:`machine.Pin` objects (or integers) specifying the MDC and MDIO pins. - ``phy_type`` - Select the PHY device type. Supported devices are + ``PHY_GENERIC``, ``PHY_LAN8710``, ``PHY_LAN8720``, ``PHY_IP101``, ``PHY_RTL8201``, ``PHY_DP83848``, ``PHY_KSZ8041`` and ``PHY_KSZ8081``. These values are all constants defined in the ``network`` module. @@ -270,8 +271,10 @@ Use the :mod:`time