diff --git a/.gitmodules b/.gitmodules index 59048d6c03..d0f3fd5656 100644 --- a/.gitmodules +++ b/.gitmodules @@ -55,3 +55,15 @@ [submodule "frozen/Adafruit_CircuitPython_HID"] path = frozen/Adafruit_CircuitPython_HID url = https://github.com/adafruit/Adafruit_CircuitPython_HID.git +[submodule "ports/atmel-samd/Adafruit_CircuitPython_Motor"] + path = frozen/Adafruit_CircuitPython_Motor + url = https://github.com/adafruit/Adafruit_CircuitPython_Motor.git +[submodule "ports/atmel-samd/Adafruit_CircuitPython_seesaw"] + path = frozen/Adafruit_CircuitPython_seesaw + url = https://github.com/adafruit/Adafruit_CircuitPython_seesaw.git +[submodule "frozen/Adafruit_CircuitPython_IRRemote"] + path = frozen/Adafruit_CircuitPython_IRRemote + url = https://github.com/adafruit/Adafruit_CircuitPython_IRRemote.git +[submodule "frozen/Adafruit_CircuitPython_DotStar"] + path = frozen/Adafruit_CircuitPython_DotStar + url = https://github.com/adafruit/Adafruit_CircuitPython_DotStar.git diff --git a/.travis.yml b/.travis.yml index 1e18640c81..986e32cc43 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,11 +6,13 @@ compiler: env: - TRAVIS_BOARD=arduino_zero - TRAVIS_BOARD=circuitplayground_express + - TRAVIS_BOARD=circuitplayground_express_crickit - TRAVIS_BOARD=feather_m0_basic - TRAVIS_BOARD=feather_m0_adalogger - TRAVIS_BOARD=feather_m0_rfm69 - TRAVIS_BOARD=feather_m0_rfm9x - TRAVIS_BOARD=feather_m0_express + - TRAVIS_BOARD=feather_m0_express_crickit - TRAVIS_BOARD=feather_m4_express - TRAVIS_BOARD=itsybitsy_m0_express - TRAVIS_BOARD=itsybitsy_m4_express @@ -42,7 +44,11 @@ notifications: before_script: - sudo dpkg --add-architecture i386 - - sudo apt-get install -y python3 gcc-multilib pkg-config libffi-dev libffi-dev:i386 qemu-system + - | + sudo apt-get install -y python3 gcc-multilib pkg-config libffi-dev libffi-dev:i386 qemu-system || + sleep 30 || + sudo apt-get install -y python3 gcc-multilib pkg-config libffi-dev libffi-dev:i386 qemu-system + - ([[ -z "$TRAVIS_TEST" ]] || sudo apt-get install -y qemu-system) - ([[ -z "$TRAVIS_BOARD" ]] || (wget https://s3.amazonaws.com/adafruit-circuit-python/gcc-arm-embedded_7-2017q4-1~trusty3_amd64.deb && sudo dpkg -i gcc-arm-embedded*_amd64.deb)) - ([[ $TRAVIS_TEST != "qemu" ]] || (wget https://s3.amazonaws.com/adafruit-circuit-python/gcc-arm-embedded_7-2017q4-1~trusty3_amd64.deb && sudo dpkg -i gcc-arm-embedded*_amd64.deb)) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2eb0214da4..6feed085c5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,12 +5,6 @@ By participating in this project you agree to abide by its terms. Participation covers any forum used to converse about CircuitPython including unofficial and official spaces. Failure to do so will result in corrective actions such as time out or ban from the project. -## Developer contact -[@tannewt](https://github.com/tannewt) is the main developer of CircuitPython -and is sponsored by [Adafruit Industries LLC](https://adafruit.com). He is -reachable on [Discord](https://adafru.it/discord) as tannewt during US West Coast -working hours. He also checks GitHub issues and the [Adafruit support forum](https://forums.adafruit.com/viewforum.php?f=60). - ## Licensing By contributing to this repository you are certifying that you have all necessary permissions to license the code under an MIT License. You still retain the @@ -20,6 +14,23 @@ If you have an employment contract with your employer please make sure that they don't automatically own your work product. Make sure to get any necessary approvals before contributing. Another term for this contribution off-hours is moonlighting. +## Getting started +CircuitPython developer Dan Halbert (@dhalbert) has written up build instructions using native build +tools [here](https://learn.adafruit.com/building-circuitpython). + +For SAMD21 debugging workflow tips check out [this learn guide](https://learn.adafruit.com/debugging-the-samd21-with-gdb) from Scott (@tannewt). + +## Developer contacts +Scott Shawcroft ([@tannewt](https://github.com/tannewt)) is the lead developer of CircuitPython +and is sponsored by [Adafruit Industries LLC](https://adafruit.com). Scott is usually available +during US West Coast working hours. Dan Halbert ([@dhalbert](https://github.com/dhalbert)) and +Kattni Rembor ([@kattni](https://github.com/kattni)) are also sponsored by [Adafruit Industries + LLC](https://adafruit.com) and are usually available during US East Coast daytime hours including +some weekends. + +They are all reachable on [Discord](https://adafru.it/discord), GitHub issues and the [Adafruit +support forum](https://forums.adafruit.com/viewforum.php?f=60). + ## Code guidelines We aim to keep our code and commit style compatible with MicroPython upstream. Please review their diff --git a/README.rst b/README.rst index 6017be207c..a1b90fa02a 100644 --- a/README.rst +++ b/README.rst @@ -103,10 +103,15 @@ Differences from `MicroPython `__ CircuitPython: -- includes a port for Atmel SAMD21 (Commonly known as M0 in Adafruit - product names.) -- supports only Atmel SAMD21 and ESP8266 ports. +- includes a ports for MicroChip SAMD21 (Commonly known as M0 in Adafruit + product names and SAMD51 (M4). +- supports only SAMD21, SAMD51, and ESP8266 ports. An nRF port is under + development. - tracks MicroPython's releases (not master). +- Longints (arbitrary-length integers) are enabled for most M0 + Express boards (those boards with SPI flash chips external + to the microcontroller), and for all M4 builds. + Longints are disabled on other boards due to lack of flash space. Behavior ~~~~~~~~ diff --git a/conf.py b/conf.py index eb4b1490f7..03d100f121 100644 --- a/conf.py +++ b/conf.py @@ -101,6 +101,7 @@ exclude_patterns = ["**/build*", "ports/atmel-samd/asf4_conf", "ports/atmel-samd/external_flash", "ports/atmel-samd/freetouch", + "ports/atmel-samd/peripherals", "ports/atmel-samd/QTouch", "ports/atmel-samd/tools", "ports/bare-arm", diff --git a/docs/c2rst.py b/docs/c2rst.py index 9ca8bc1bb3..904fb74084 100644 --- a/docs/c2rst.py +++ b/docs/c2rst.py @@ -7,6 +7,7 @@ class CStrip(sphinx.parsers.Parser): def parse(self, inputstring, document): # This setting is missing starting with Sphinx 1.7.1 so we set it ourself. document.settings.tab_width = 4 + document.settings.character_level_inline_markup = False stripped = [] for line in inputstring.split("\n"): line = line.strip() diff --git a/docs/design_guide.rst b/docs/design_guide.rst index a1524eaa2b..e7b3832bcb 100644 --- a/docs/design_guide.rst +++ b/docs/design_guide.rst @@ -441,10 +441,10 @@ buffers. Examples ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -ustruct.pack +struct.pack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use `ustruct.pack_into` instead of `ustruct.pack`. +Use `struct.pack_into` instead of `struct.pack`. Sensor properties and units -------------------------------------------------------------------------------- diff --git a/docs/library/array.rst b/docs/library/array.rst index dfaef0ff6c..0f1310b687 100644 --- a/docs/library/array.rst +++ b/docs/library/array.rst @@ -1,8 +1,6 @@ :mod:`array` -- arrays of numeric data ====================================== -.. include:: ../templates/unsupported_in_circuitpython.inc - .. module:: array :synopsis: efficient arrays of numeric data diff --git a/docs/library/builtins.rst b/docs/library/builtins.rst index b45b6fe380..36a84bc0c5 100644 --- a/docs/library/builtins.rst +++ b/docs/library/builtins.rst @@ -1,18 +1,14 @@ Builtin functions and exceptions ================================ -.. warning:: - - These builtins are inherited from MicroPython and may not work in CircuitPython - as documented or at all! If work differently from CPython, then their behavior - may change. - All builtin functions and exceptions are described here. They are also available via ``builtins`` module. Functions and types ------------------- +Not all of these functions and types are turned on in all CircuitPython ports, for space reasons. + .. function:: abs() .. function:: all() @@ -62,6 +58,8 @@ Functions and types .. class:: frozenset() +`frozenset()` is not enabled on non-Express CircuitPython boards. + .. function:: getattr() .. function:: globals() @@ -80,12 +78,12 @@ Functions and types .. classmethod:: from_bytes(bytes, byteorder) - In MicroPython, `byteorder` parameter must be positional (this is + In CircuitPython, `byteorder` parameter must be positional (this is compatible with CPython). .. method:: to_bytes(size, byteorder) - In MicroPython, `byteorder` parameter must be positional (this is + In CircuitPython, `byteorder` parameter must be positional (this is compatible with CPython). .. function:: isinstance() @@ -130,6 +128,8 @@ Functions and types .. function:: reversed() +`reversed()` is not enabled on non-Express CircuitPython boards. + .. function:: round() .. class:: set() @@ -182,12 +182,16 @@ Exceptions .. exception:: OSError - |see_cpython| `OSError`. MicroPython doesn't implement ``errno`` + |see_cpython| `OSError`. CircuitPython doesn't implement the ``errno`` attribute, instead use the standard way to access exception arguments: ``exc.args[0]``. .. exception:: RuntimeError +.. exception:: ReloadException + + `ReloadException` is used internally to deal with soft restarts. + .. exception:: StopIteration .. exception:: SyntaxError diff --git a/docs/library/gc.rst b/docs/library/gc.rst index 01bd925e99..1a6c3d68c0 100644 --- a/docs/library/gc.rst +++ b/docs/library/gc.rst @@ -31,7 +31,7 @@ Functions .. admonition:: Difference to CPython :class: attention - This function is MicroPython extension. + This function is a MicroPython extension. .. function:: mem_free() @@ -41,7 +41,7 @@ Functions .. admonition:: Difference to CPython :class: attention - This function is MicroPython extension. + This function is a MicroPython extension. .. function:: threshold([amount]) @@ -63,6 +63,6 @@ Functions .. admonition:: Difference to CPython :class: attention - This function is a MicroPython extension. CPython has a similar + This function is a a MicroPython extension. CPython has a similar function - ``set_threshold()``, but due to different GC implementations, its signature and semantics are different. diff --git a/docs/library/index.rst b/docs/library/index.rst index c7b6879aa4..6c2e576e7d 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -3,43 +3,74 @@ MicroPython libraries ===================== -.. warning:: - - These modules are inherited from MicroPython and may not work in CircuitPython - as documented or at all! If they do work, they may change at any time. - - Python standard libraries and micro-libraries --------------------------------------------- +These libraries are inherited from MicroPython. +They are similar to the standard Python libraries with the same name +or with the "u" prefix dropped. +They implement a subset of or a variant of the corresponding +standard Python library. + +.. warning:: + + Though these MicroPython-based libraries are available in CircuitPython, + their functionality may change in the future, perhaps significantly. + As CircuitPython continues to develop, new versions of these libraries will + be created that are more compliant with the standard Python libraries. + You may need to change your code later if you rely + on any non-standard functionality they currently provide. + +CircuitPython's goal long-term goalis that code written in CircuitPython +using Python standard libraries will be runnable on CPython without changes. + +Some libraries below are not enabled on CircuitPython builds with +limited flash memory, usually on non-Express builds: +``uerrno``, ``ure``. + +Some libraries are not currently enabled in any CircuitPython build, but may be in the future: +``uio``, ``ujson``, ``uzlib``. + +Some libraries are only enabled only WiFi-capable ports (ESP8266, nRF) +because they are typically used for network software: +``binascii``, ``hashlib``, ``uheapq``, ``uselect``, ``ussl``. +Not all of these are enabled on all WiFi-capable ports. .. toctree:: :maxdepth: 1 builtins.rst + uheapq.rst array.rst - gc.rst - sys.rst binascii.rst collections.rst - uerrno.rst + gc.rst hashlib.rst - uheapq.rst + sys.rst + uerrno.rst uio.rst ujson.rst ure.rst uselect.rst usocket.rst ussl.rst - ustruct.rst uzlib.rst +Omitted functions in the ``string`` library +------------------------------------------- -MicroPython-specific libraries ------------------------------- +A few string operations are not enabled on CircuitPython +M0 non-Express builds, due to limited flash memory: +``string.center()``, ``string.partition()``, ``string.splitlines()``, +``string.reversed()``. -Functionality specific to the MicroPython implementation is available in -the following libraries. + +CircuitPython/MicroPython-specific libraries +-------------------------------------------- + +Functionality specific to the CircuitPython/MicroPython implementation is available in +the following libraries. These libraries may change signficantly or be removed in future +versions of CircuitPtyon. .. toctree:: :maxdepth: 1 diff --git a/docs/library/sys.rst b/docs/library/sys.rst index de2ec2dcd2..bb92850b89 100644 --- a/docs/library/sys.rst +++ b/docs/library/sys.rst @@ -45,12 +45,12 @@ Constants .. data:: implementation Object with information about the current Python implementation. For - MicroPython, it has following attributes: + CircuitPython, it has following attributes: - * *name* - string "micropython" + * *name* - string "circuitpython" * *version* - tuple (major, minor, micro), e.g. (1, 7, 0) - This object is the recommended way to distinguish MicroPython from other + This object is the recommended way to distinguish CircuitPython from other Python implementations (note that it still may not exist in the very minimal ports). @@ -58,13 +58,13 @@ Constants :class: attention CPython mandates more attributes for this object, but the actual useful - bare minimum is implemented in MicroPython. + bare minimum is implemented in CircuitPython. .. data:: maxsize Maximum value which a native integer type can hold on the current platform, - or maximum value representable by MicroPython integer type, if it's smaller - than platform max value (that is the case for MicroPython ports without + or maximum value representable by CircuitPython integer type, if it's smaller + than platform max value (that is the case for CircuitPython ports without long int support). This attribute is useful for detecting "bitness" of a platform (32-bit vs @@ -96,11 +96,11 @@ Constants .. data:: platform - The platform that MicroPython is running on. For OS/RTOS ports, this is + The platform that CircuitPython is running on. For OS/RTOS ports, this is usually an identifier of the OS, e.g. ``"linux"``. For baremetal ports it - is an identifier of a board, e.g. ``"pyboard"`` for the original MicroPython - reference board. It thus can be used to distinguish one board from another. - If you need to check whether your program runs on MicroPython (vs other + is an identifier of the chip on a board, e.g. ``"MicroChip SAMD51"``. + It thus can be used to distinguish one board from another. + If you need to check whether your program runs on CircuitPython (vs other Python implementation), use `sys.implementation` instead. .. data:: stderr diff --git a/docs/library/ustruct.rst b/docs/library/ustruct.rst deleted file mode 100644 index c378a94bbe..0000000000 --- a/docs/library/ustruct.rst +++ /dev/null @@ -1,44 +0,0 @@ -:mod:`ustruct` -- pack and unpack primitive data types -====================================================== - -.. include:: ../templates/unsupported_in_circuitpython.inc - -.. module:: ustruct - :synopsis: pack and unpack primitive data types - -|see_cpython_module| :mod:`cpython:struct`. - -Supported size/byte order prefixes: ``@``, ``<``, ``>``, ``!``. - -Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``, -``L``, ``q``, ``Q``, ``s``, ``P``, ``f``, ``d`` (the latter 2 depending -on the floating-point support). - -Functions ---------- - -.. function:: calcsize(fmt) - - Return the number of bytes needed to store the given *fmt*. - -.. function:: pack(fmt, v1, v2, ...) - - Pack the values *v1*, *v2*, ... according to the format string *fmt*. - The return value is a bytes object encoding the values. - -.. function:: pack_into(fmt, buffer, offset, v1, v2, ...) - - Pack the values *v1*, *v2*, ... according to the format string *fmt* - into a *buffer* starting at *offset*. *offset* may be negative to count - from the end of *buffer*. - -.. function:: unpack(fmt, data) - - Unpack from the *data* according to the format string *fmt*. - The return value is a tuple of the unpacked values. - -.. function:: unpack_from(fmt, data, offset=0) - - Unpack from the *data* starting at *offset* according to the format string - *fmt*. *offset* may be negative to count from the end of *buffer*. The return - value is a tuple of the unpacked values. diff --git a/docs/templates/unsupported_in_circuitpython.inc b/docs/templates/unsupported_in_circuitpython.inc index 18c9215a84..1ed605d503 100644 --- a/docs/templates/unsupported_in_circuitpython.inc +++ b/docs/templates/unsupported_in_circuitpython.inc @@ -1,5 +1,8 @@ .. warning:: - This module is inherited from MicroPython and may not work in CircuitPython - as documented or at all! If they do work, they may change at any time. It is - unsupported. + Though this MicroPython-based library is available for use in CircuitPython, + its functionality may change in the future, perhaps significantly. + As CircuitPython continues to develop, it may be changed + to comply more closely with the corresponding standard Python library. + You may need to change your code later if you rely + on any non-standard functionality it currently provides. diff --git a/frozen/Adafruit_CircuitPython_BusDevice b/frozen/Adafruit_CircuitPython_BusDevice index de2d0d33ca..376a80e62a 160000 --- a/frozen/Adafruit_CircuitPython_BusDevice +++ b/frozen/Adafruit_CircuitPython_BusDevice @@ -1 +1 @@ -Subproject commit de2d0d33cace54532467e411128521dfc8d253c3 +Subproject commit 376a80e62acb3ba8b9a1e5c11bb75d36352f2190 diff --git a/frozen/Adafruit_CircuitPython_CircuitPlayground b/frozen/Adafruit_CircuitPython_CircuitPlayground index a669915237..d0022de9d5 160000 --- a/frozen/Adafruit_CircuitPython_CircuitPlayground +++ b/frozen/Adafruit_CircuitPython_CircuitPlayground @@ -1 +1 @@ -Subproject commit a669915237545638c64f89400f368a91c408cd5d +Subproject commit d0022de9d5e9b4c3d4998a5d708e59ee147f0a21 diff --git a/frozen/Adafruit_CircuitPython_DotStar b/frozen/Adafruit_CircuitPython_DotStar new file mode 160000 index 0000000000..af25424ee7 --- /dev/null +++ b/frozen/Adafruit_CircuitPython_DotStar @@ -0,0 +1 @@ +Subproject commit af25424ee7dbebea3e5d77390c017018ffa52d36 diff --git a/frozen/Adafruit_CircuitPython_HID b/frozen/Adafruit_CircuitPython_HID index 90e4ca931a..1da880cee3 160000 --- a/frozen/Adafruit_CircuitPython_HID +++ b/frozen/Adafruit_CircuitPython_HID @@ -1 +1 @@ -Subproject commit 90e4ca931a991718985e655bdcd527c1b0543f55 +Subproject commit 1da880cee3c2d64e2e7e4ca5082f3a74c4a37a5a diff --git a/frozen/Adafruit_CircuitPython_IRRemote b/frozen/Adafruit_CircuitPython_IRRemote new file mode 160000 index 0000000000..c29e10b590 --- /dev/null +++ b/frozen/Adafruit_CircuitPython_IRRemote @@ -0,0 +1 @@ +Subproject commit c29e10b590efbdf06163897b49cd0c2bea82ad6e diff --git a/frozen/Adafruit_CircuitPython_LIS3DH b/frozen/Adafruit_CircuitPython_LIS3DH index d5491cded0..c4152a0d87 160000 --- a/frozen/Adafruit_CircuitPython_LIS3DH +++ b/frozen/Adafruit_CircuitPython_LIS3DH @@ -1 +1 @@ -Subproject commit d5491cded0d12716ceb1111ca4c4431111a22df6 +Subproject commit c4152a0d87a04903ae0e612eb381af440c9e28b3 diff --git a/frozen/Adafruit_CircuitPython_Motor b/frozen/Adafruit_CircuitPython_Motor new file mode 160000 index 0000000000..6da5d14b98 --- /dev/null +++ b/frozen/Adafruit_CircuitPython_Motor @@ -0,0 +1 @@ +Subproject commit 6da5d14b98ac3d929662731f73ce03c0c958b520 diff --git a/frozen/Adafruit_CircuitPython_seesaw b/frozen/Adafruit_CircuitPython_seesaw new file mode 160000 index 0000000000..498f59bf92 --- /dev/null +++ b/frozen/Adafruit_CircuitPython_seesaw @@ -0,0 +1 @@ +Subproject commit 498f59bf926477b3a8fb8eb157ca05eb12c3e298 diff --git a/main.c b/main.c index bc37fa8711..fb1a9e90fb 100644 --- a/main.c +++ b/main.c @@ -168,7 +168,7 @@ bool start_mp(safe_mode_t safe_mode) { reset_status_led(); if (result.return_code & PYEXEC_FORCED_EXIT) { - return reload_next_character; + return reload_requested; } } @@ -180,7 +180,7 @@ bool start_mp(safe_mode_t safe_mode) { #ifdef MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_LOOP #endif - if (reload_next_character) { + if (reload_requested) { return true; } @@ -233,40 +233,7 @@ bool start_mp(safe_mode_t safe_mode) { } } -int __attribute__((used)) main(void) { - // initialise the cpu and peripherals - safe_mode_t safe_mode = port_init(); - - rgb_led_status_init(); - - // Stack limit should be less than real stack size, so we have a chance - // to recover from limit hit. (Limit is measured in bytes.) - mp_stack_ctrl_init(); - mp_stack_set_limit((char*)&_estack - (char*)&_ebss - 1024); - -#if MICROPY_MAX_STACK_USAGE - // _ezero (same as _ebss) is an int, so start 4 bytes above it. - mp_stack_set_bottom(&_ezero + 1); - mp_stack_fill_with_sentinel(); -#endif - - // Create a new filesystem only if we're not in a safe mode. - // A power brownout here could make it appear as if there's - // no SPI flash filesystem, and we might erase the existing one. - filesystem_init(safe_mode == NO_SAFE_MODE, false); - - // Reset everything and prep MicroPython to run boot.py. - reset_port(); - reset_board(); - reset_mp(); - - // Turn on autoreload by default but before boot.py in case it wants to change it. - autoreload_enable(); - - // By default our internal flash is readonly to local python code and - // writable over USB. Set it here so that boot.py can change it. - filesystem_writable_by_python(false); - +void run_boot_py(safe_mode_t safe_mode) { // If not in safe mode, run boot before initing USB and capture output in a // file. if (filesystem_present() && safe_mode == NO_SAFE_MODE && MP_STATE_VM(vfs_mount_table) != NULL) { @@ -329,8 +296,8 @@ int __attribute__((used)) main(void) { if (!skip_boot_output) { f_close(boot_output_file); filesystem_flush(); - boot_output_file = NULL; } + boot_output_file = NULL; #endif // Reset to remove any state that boot.py setup. It should only be used to @@ -338,6 +305,43 @@ int __attribute__((used)) main(void) { reset_port(); reset_mp(); } +} + +int __attribute__((used)) main(void) { + // initialise the cpu and peripherals + safe_mode_t safe_mode = port_init(); + + rgb_led_status_init(); + + // Stack limit should be less than real stack size, so we have a chance + // to recover from limit hit. (Limit is measured in bytes.) + mp_stack_set_top((char*)&_estack); + mp_stack_set_limit((char*)&_estack - (char*)&_ebss - 1024); + +#if MICROPY_MAX_STACK_USAGE + // _ezero (same as _ebss) is an int, so start 4 bytes above it. + mp_stack_set_bottom(&_ezero + 1); + mp_stack_fill_with_sentinel(); +#endif + + // Create a new filesystem only if we're not in a safe mode. + // A power brownout here could make it appear as if there's + // no SPI flash filesystem, and we might erase the existing one. + filesystem_init(safe_mode == NO_SAFE_MODE, false); + + // Reset everything and prep MicroPython to run boot.py. + reset_port(); + reset_board(); + reset_mp(); + + // Turn on autoreload by default but before boot.py in case it wants to change it. + autoreload_enable(); + + // By default our internal flash is readonly to local python code and + // writable over USB. Set it here so that boot.py can change it. + filesystem_writable_by_python(false); + + run_boot_py(safe_mode); // Start serial and HID after giving boot.py a chance to tweak behavior. serial_init(); diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index e85a11b570..1a406c1d01 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -112,8 +112,7 @@ else # -finline-limit=80 or so is similar to not having it on. # There is no simple default value, though. ifdef INTERNAL_FLASH_FILESYSTEM - ## Not currently needed - ## CFLAGS += -finline-limit=50 + CFLAGS += -finline-limit=60 endif CFLAGS += -flto endif @@ -165,6 +164,20 @@ ifndef INTERNAL_LIBM LIBS += -lm endif +# Propagate longint choice from .mk to C. There's no easy string comparison +# in cpp coniditionals, so we #define separate names for each. +ifeq ($(LONGINT_IMPL),NONE) +CFLAGS += -DLONGINT_IMPL_NONE +endif + +ifeq ($(LONGINT_IMPL),MPZ) +CFLAGS += -DLONGINT_IMPL_MPZ +endif + +ifeq ($(LONGINT_IMPL),LONGLONG) +CFLAGS += -DLONGINT_IMPL_LONGLONG +endif + ifeq ($(CHIP_FAMILY), samd21) LDFLAGS += -mthumb -mcpu=cortex-m0plus -Lasf/thirdparty/CMSIS/Lib/GCC/ BOOTLOADER_SIZE := 0x2000 @@ -227,20 +240,28 @@ SRC_ASF := $(addprefix asf4/$(CHIP_FAMILY)/, $(SRC_ASF)) SRC_C = \ audio_dma.c \ + board_busses.c \ background.c \ - clocks.c \ - $(CHIP_FAMILY)_clocks.c \ - events.c \ fatfs_port.c \ flash_api.c \ mphalport.c \ reset.c \ - $(CHIP_FAMILY)_peripherals.c \ - peripherals.c \ - $(CHIP_FAMILY)_pins.c \ - shared_dma.c \ + peripherals/clocks.c \ + peripherals/dma.c \ + peripherals/events.c \ + peripherals/external_interrupts.c \ + peripherals/sercom.c \ + peripherals/timers.c \ + peripherals/$(CHIP_FAMILY)/adc.c \ + peripherals/$(CHIP_FAMILY)/cache.c \ + peripherals/$(CHIP_FAMILY)/clocks.c \ + peripherals/$(CHIP_FAMILY)/dma.c \ + peripherals/$(CHIP_FAMILY)/events.c \ + peripherals/$(CHIP_FAMILY)/external_interrupts.c \ + peripherals/$(CHIP_FAMILY)/pins.c \ + peripherals/$(CHIP_FAMILY)/sercom.c \ + peripherals/$(CHIP_FAMILY)/timers.c \ tick.c \ - timers.c \ usb.c \ usb_mass_storage.c \ bindings/samd/__init__.c \ @@ -259,7 +280,7 @@ SRC_C = \ lib/libc/string0.c \ lib/mp-readline/readline.c \ $(BUILD)/autogen_usb_descriptor.c \ - # freetouch/adafruit_ptc.c + freetouch/adafruit_ptc.c # Choose which flash filesystem impl to use. # (Right now INTERNAL_FLASH_FILESYSTEM and SPI_FLASH_FILESYSTEM are mutually exclusive. @@ -287,6 +308,8 @@ SRC_COMMON_HAL = \ microcontroller/Processor.c \ neopixel_write/__init__.c \ os/__init__.c \ + rotaryio/__init__.c \ + rotaryio/IncrementalEncoder.c \ rtc/__init__.c \ rtc/RTC.c \ storage/__init__.c \ @@ -306,7 +329,7 @@ SRC_COMMON_HAL = \ usb_hid/Device.c \ audioio/__init__.c \ audioio/AudioOut.c \ -# touchio/__init__.c \ + touchio/__init__.c \ touchio/TouchIn.c \ ifeq ($(INTERNAL_LIBM),1) @@ -377,7 +400,7 @@ ifneq ($(CHIP_VARIANT),SAMD51G18A) audiobusio/__init__.c \ audiobusio/I2SOut.c \ audiobusio/PDMIn.c - SRC_C += i2s.c + SRC_C += peripherals/i2s.c peripherals/$(CHIP_FAMILY)/i2s.c endif endif diff --git a/ports/atmel-samd/audio_dma.c b/ports/atmel-samd/audio_dma.c index e8dbdc61d6..5a572e9d1f 100644 --- a/ports/atmel-samd/audio_dma.c +++ b/ports/atmel-samd/audio_dma.c @@ -25,9 +25,9 @@ */ #include "audio_dma.h" -#include "clocks.h" -#include "events.h" -#include "shared_dma.h" +#include "peripherals/clocks.h" +#include "peripherals/events.h" +#include "peripherals/dma.h" #include "shared-bindings/audioio/RawSample.h" #include "shared-bindings/audioio/WaveFile.h" diff --git a/ports/atmel-samd/bindings/samd/Clock.c b/ports/atmel-samd/bindings/samd/Clock.c index 81e8fb1cec..3c87177a46 100644 --- a/ports/atmel-samd/bindings/samd/Clock.c +++ b/ports/atmel-samd/bindings/samd/Clock.c @@ -24,9 +24,8 @@ * THE SOFTWARE. */ -#include "clocks.h" #include "bindings/samd/Clock.h" - +#include "peripherals/clocks.h" #include "py/obj.h" #include "py/objproperty.h" #include "py/runtime.h" diff --git a/ports/atmel-samd/board_busses.c b/ports/atmel-samd/board_busses.c new file mode 100644 index 0000000000..008391bf0a --- /dev/null +++ b/ports/atmel-samd/board_busses.c @@ -0,0 +1,113 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/busio/I2C.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/busio/UART.h" + +#include "shared-bindings/microcontroller/Pin.h" +#include "mpconfigboard.h" +#include "peripherals/pins.h" +#include "py/runtime.h" + +#if !defined(DEFAULT_I2C_BUS_SDA) || !defined(DEFAULT_I2C_BUS_SCL) + STATIC mp_obj_t board_i2c(void) { + mp_raise_NotImplementedError("No default I2C bus"); + return NULL; + } +#else + STATIC mp_obj_t i2c_singleton = NULL; + + STATIC mp_obj_t board_i2c(void) { + + if (i2c_singleton == NULL) { + busio_i2c_obj_t *self = m_new_obj(busio_i2c_obj_t); + self->base.type = &busio_i2c_type; + + assert_pin_free(DEFAULT_I2C_BUS_SDA); + assert_pin_free(DEFAULT_I2C_BUS_SCL); + common_hal_busio_i2c_construct(self, DEFAULT_I2C_BUS_SCL, DEFAULT_I2C_BUS_SDA, 400000, 0); + i2c_singleton = (mp_obj_t)self; + } + return i2c_singleton; + + } +#endif +MP_DEFINE_CONST_FUN_OBJ_0(board_i2c_obj, board_i2c); + +#if !defined(DEFAULT_SPI_BUS_SCK) || !defined(DEFAULT_SPI_BUS_MISO) || !defined(DEFAULT_SPI_BUS_MOSI) + STATIC mp_obj_t board_spi(void) { + mp_raise_NotImplementedError("No default SPI bus"); + return NULL; + } +#else + STATIC mp_obj_t spi_singleton = NULL; + + STATIC mp_obj_t board_spi(void) { + + if (spi_singleton == NULL) { + busio_spi_obj_t *self = m_new_obj(busio_spi_obj_t); + self->base.type = &busio_spi_type; + assert_pin_free(DEFAULT_SPI_BUS_SCK); + assert_pin_free(DEFAULT_SPI_BUS_MOSI); + assert_pin_free(DEFAULT_SPI_BUS_MISO); + const mcu_pin_obj_t* clock = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_SCK); + const mcu_pin_obj_t* mosi = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_MOSI); + const mcu_pin_obj_t* miso = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_MISO); + common_hal_busio_spi_construct(self, clock, mosi, miso); + spi_singleton = (mp_obj_t)self; + } + return spi_singleton; + } +#endif +MP_DEFINE_CONST_FUN_OBJ_0(board_spi_obj, board_spi); + +#if !defined(DEFAULT_UART_BUS_RX) || !defined(DEFAULT_UART_BUS_TX) + STATIC mp_obj_t board_uart(void) { + mp_raise_NotImplementedError("No default UART bus"); + return NULL; + } +#else + STATIC mp_obj_t uart_singleton = NULL; + + STATIC mp_obj_t board_uart(void) { + if (uart_singleton == NULL) { + busio_uart_obj_t *self = m_new_obj(busio_uart_obj_t); + self->base.type = &busio_uart_type; + + assert_pin_free(DEFAULT_UART_BUS_RX); + assert_pin_free(DEFAULT_UART_BUS_TX); + + const mcu_pin_obj_t* rx = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_RX); + const mcu_pin_obj_t* tx = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_TX); + + common_hal_busio_uart_construct(self, tx, rx, 9600, 8, PARITY_NONE, 1, 1000, 64); + uart_singleton = (mp_obj_t)self; + } + return uart_singleton; + } +#endif +MP_DEFINE_CONST_FUN_OBJ_0(board_uart_obj, board_uart); diff --git a/ports/atmel-samd/board_busses.h b/ports/atmel-samd/board_busses.h new file mode 100644 index 0000000000..a368885a58 --- /dev/null +++ b/ports/atmel-samd/board_busses.h @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_BUSSES_H +#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_BUSSES_H + +void board_i2c(void); +extern mp_obj_fun_builtin_fixed_t board_i2c_obj; + +void board_spi(void); +extern mp_obj_fun_builtin_fixed_t board_spi_obj; + +void board_uart(void); +extern mp_obj_fun_builtin_fixed_t board_uart_obj; + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_BUSSES_H diff --git a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h index 6eeddb36c7..a32f128f52 100644 --- a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h +++ b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h @@ -14,3 +14,13 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) + +#define DEFAULT_I2C_BUS_SCL (&pin_PA23) +#define DEFAULT_I2C_BUS_SDA (&pin_PA22) + +#define DEFAULT_SPI_BUS_SCK (&pin_PB11) +#define DEFAULT_SPI_BUS_MOSI (&pin_PB10) +#define DEFAULT_SPI_BUS_MISO (&pin_PA12) + +#define DEFAULT_UART_BUS_RX (&pin_PA11) +#define DEFAULT_UART_BUS_TX (&pin_PA10) diff --git a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk index b24cc9c647..017e66ddff 100644 --- a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk +++ b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk @@ -5,6 +5,7 @@ USB_PRODUCT = "Arduino Zero" USB_MANUFACTURER = "Arduino" INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = NONE CHIP_VARIANT = SAMD21G18A CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/arduino_zero/pins.c b/ports/atmel-samd/boards/arduino_zero/pins.c index 8b28c0fc22..8a7ff70e6d 100644 --- a/ports/atmel-samd/boards/arduino_zero/pins.c +++ b/ports/atmel-samd/boards/arduino_zero/pins.c @@ -1,6 +1,6 @@ #include "shared-bindings/board/__init__.h" -#include "samd21_pins.h" +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, @@ -30,5 +30,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) }, { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) }, { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/circuitplayground_express/board.c b/ports/atmel-samd/boards/circuitplayground_express/board.c index eb7ffab4a2..5c5e9f7faf 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/board.c +++ b/ports/atmel-samd/boards/circuitplayground_express/board.c @@ -31,7 +31,6 @@ #include "hal/include/hal_gpio.h" #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/neopixel_write/__init__.h" -#include "samd21_pins.h" void board_init(void) { diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h index 73d45f2cf8..3d97e2cb19 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h @@ -58,3 +58,13 @@ // Explanation of how a user got into safe mode. #define BOARD_USER_SAFE_MODE_ACTION "pressing both buttons at start up" + +#define DEFAULT_I2C_BUS_SCL (&pin_PB03) +#define DEFAULT_I2C_BUS_SDA (&pin_PB02) + +#define DEFAULT_SPI_BUS_SCK (&pin_PA05) +#define DEFAULT_SPI_BUS_MOSI (&pin_PA07) +#define DEFAULT_SPI_BUS_MISO (&pin_PA06) + +#define DEFAULT_UART_BUS_RX (&pin_PB09) +#define DEFAULT_UART_BUS_TX (&pin_PB08) diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk index 4d6e32eb7b..831106adc8 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk @@ -5,6 +5,7 @@ USB_PRODUCT = "CircuitPlayground Express" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/circuitplayground_express/pins.c b/ports/atmel-samd/boards/circuitplayground_express/pins.c index aecd7f416a..14ae89c55e 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/pins.c +++ b/ports/atmel-samd/boards/circuitplayground_express/pins.c @@ -1,4 +1,6 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, @@ -56,5 +58,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA05) }, { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/board.c b/ports/atmel-samd/boards/circuitplayground_express_crickit/board.c new file mode 100644 index 0000000000..5c5e9f7faf --- /dev/null +++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/board.c @@ -0,0 +1,65 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "boards/board.h" +#include "common-hal/microcontroller/Pin.h" +#include "hal/include/hal_gpio.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/neopixel_write/__init__.h" + +void board_init(void) +{ +} + +// Check the status of the two buttons on CircuitPlayground Express. If both are +// pressed, then boot into user safe mode. +bool board_requests_safe_mode(void) { + gpio_set_pin_function(PIN_PA14, GPIO_PIN_FUNCTION_OFF); + gpio_set_pin_direction(PIN_PA14, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(PIN_PA14, GPIO_PULL_DOWN); + + gpio_set_pin_function(PIN_PA28, GPIO_PIN_FUNCTION_OFF); + gpio_set_pin_direction(PIN_PA28, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(PIN_PA28, GPIO_PULL_DOWN); + bool safe_mode = gpio_get_pin_level(PIN_PA14) && + gpio_get_pin_level(PIN_PA28); + reset_pin(PIN_PA14); + reset_pin(PIN_PA28); + return safe_mode; +} + +void reset_board(void) { + uint8_t empty[30]; + memset(empty, 0, 30); + digitalio_digitalinout_obj_t neopixel_pin; + common_hal_digitalio_digitalinout_construct(&neopixel_pin, &pin_PB23); + common_hal_digitalio_digitalinout_switch_to_output(&neopixel_pin, false, + DRIVE_MODE_PUSH_PULL); + common_hal_neopixel_write(&neopixel_pin, empty, 30); + common_hal_digitalio_digitalinout_deinit(&neopixel_pin); +} diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h new file mode 100644 index 0000000000..83cc19d9f3 --- /dev/null +++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h @@ -0,0 +1,73 @@ +#define MICROPY_HW_BOARD_NAME "Adafruit CircuitPlayground Express with Crickit libraries" +#define MICROPY_HW_MCU_NAME "samd21g18" + +// No framebuf on CRICKit version to save space. +#define MICROPY_PY_FRAMEBUF (0) + +// Don't allow touch on A0 (PA02), because it's connected to the speaker. +#define PA02_NO_TOUCH (true) + +// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz. +#define SPI_FLASH_BAUDRATE (8000000) + +// On-board flash +#define SPI_FLASH_MOSI_PIN PIN_PA20 +#define SPI_FLASH_MISO_PIN PIN_PA16 +#define SPI_FLASH_SCK_PIN PIN_PA21 +#define SPI_FLASH_CS_PIN PIN_PB22 + +#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA20D_SERCOM3_PAD2 +#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA16D_SERCOM3_PAD0 +#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA21D_SERCOM3_PAD3 +#define SPI_FLASH_SERCOM SERCOM3 +#define SPI_FLASH_SERCOM_INDEX 3 +#define SPI_FLASH_MOSI_PAD 2 +#define SPI_FLASH_MISO_PAD 0 +#define SPI_FLASH_SCK_PAD 3 + +// Transmit Data Pinout +// <0x0=>PAD[0,1]_DO_SCK +// <0x1=>PAD[2,3]_DO_SCK +// <0x2=>PAD[3,1]_DO_SCK +// <0x3=>PAD[0,3]_DO_SCK +#define SPI_FLASH_DOPO 1 +#define SPI_FLASH_DIPO 0 // same as MISO PAD + +// These are pins not to reset. +// PA24 and PA25 are USB. +#define MICROPY_PORT_A (PORT_PA16 | PORT_PA20 | PORT_PA21 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_B (PORT_PB22) +#define MICROPY_PORT_C (0) + +#define SPEAKER_ENABLE_PIN (&pin_PA30) + +#include "external_flash/devices.h" + +// If you change this, then make sure to update the linker scripts as well to +// make sure you don't overwrite code. +#define CIRCUITPY_INTERNAL_NVM_SIZE 256 + +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +#include "external_flash/devices.h" + +#define EXTERNAL_FLASH_DEVICE_COUNT 2 +#define EXTERNAL_FLASH_DEVICES S25FL216K, \ + GD25Q16C + +#include "external_flash/external_flash.h" + +#define CALIBRATE_CRYSTALLESS 1 + +// Explanation of how a user got into safe mode. +#define BOARD_USER_SAFE_MODE_ACTION "pressing both buttons at start up" + +#define DEFAULT_I2C_BUS_SCL (&pin_PB03) +#define DEFAULT_I2C_BUS_SDA (&pin_PB02) + +#define DEFAULT_SPI_BUS_SCK (&pin_PA05) +#define DEFAULT_SPI_BUS_MOSI (&pin_PA07) +#define DEFAULT_SPI_BUS_MISO (&pin_PA06) + +#define DEFAULT_UART_BUS_RX (&pin_PB09) +#define DEFAULT_UART_BUS_TX (&pin_PB08) diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk new file mode 100644 index 0000000000..0145bf7850 --- /dev/null +++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk @@ -0,0 +1,21 @@ +LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld +USB_VID = 0x239A +USB_PID = 0x8019 +USB_PRODUCT = "CircuitPlayground Express with Crickit libraries" +USB_MANUFACTURER = "Adafruit Industries LLC" + +SPI_FLASH_FILESYSTEM = 1 +# Turn off longints for Crickit build to make room for additional frozen libs. +LONGINT_IMPL = NONE + +CHIP_VARIANT = SAMD21G18A +CHIP_FAMILY = samd21 + +# Include these Python libraries in firmware. +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_CircuitPlayground +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Motor +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_seesaw +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Thermistor diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/pins.c b/ports/atmel-samd/boards/circuitplayground_express_crickit/pins.c new file mode 100644 index 0000000000..14ae89c55e --- /dev/null +++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/pins.c @@ -0,0 +1,65 @@ +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PB03) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PB03) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PB03) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_TEMPERATURE), MP_ROM_PTR(&pin_PA09) }, + { MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_PA09) }, + + { MP_ROM_QSTR(MP_QSTR_BUTTON_A), MP_ROM_PTR(&pin_PA28) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA28) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_B), MP_ROM_PTR(&pin_PA14) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA14) }, + { MP_ROM_QSTR(MP_QSTR_SLIDE_SWITCH), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB23) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PB23) }, + + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, + + { MP_ROM_QSTR(MP_QSTR_REMOTEIN), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_IR_RX), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_REMOTEOUT), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_IR_TX), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_IR_PROXIMITY), MP_ROM_PTR(&pin_PA04) }, + + { MP_ROM_QSTR(MP_QSTR_MICROPHONE_CLOCK), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_MICROPHONE_DATA), MP_ROM_PTR(&pin_PA08) }, + + { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_INTERRUPT), MP_ROM_PTR(&pin_PA13) }, + { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_SDA), MP_ROM_PTR(&pin_PA00) }, + { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_SCL), MP_ROM_PTR(&pin_PA01) }, + + { MP_ROM_QSTR(MP_QSTR_SPEAKER_ENABLE), MP_ROM_PTR(&pin_PA30) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h index 8802d39d99..94caa7d040 100644 --- a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h @@ -12,3 +12,13 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) + +#define DEFAULT_I2C_BUS_SCL (&pin_PA22) +#define DEFAULT_I2C_BUS_SDA (&pin_PA23) + +#define DEFAULT_SPI_BUS_SCK (&pin_PB11) +#define DEFAULT_SPI_BUS_MOSI (&pin_PB10) +#define DEFAULT_SPI_BUS_MISO (&pin_PA12) + +#define DEFAULT_UART_BUS_RX (&pin_PA11) +#define DEFAULT_UART_BUS_TX (&pin_PA10) diff --git a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk index debd3d775c..4f2855d732 100644 --- a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk @@ -5,6 +5,7 @@ USB_PRODUCT = "Feather M0 Adalogger" USB_MANUFACTURER = "Adafruit Industries LLC" INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = NONE CHIP_VARIANT = SAMD21G18A CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/feather_m0_adalogger/pins.c b/ports/atmel-samd/boards/feather_m0_adalogger/pins.c index a229b6bab1..0754617ddd 100644 --- a/ports/atmel-samd/boards/feather_m0_adalogger/pins.c +++ b/ports/atmel-samd/boards/feather_m0_adalogger/pins.c @@ -1,4 +1,6 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, @@ -30,5 +32,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, { MP_ROM_QSTR(MP_QSTR_RED_LED), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h index 04cbc4ff8a..34de8e1660 100644 --- a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h @@ -13,3 +13,13 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) + +#define DEFAULT_I2C_BUS_SCL (&pin_PA23) +#define DEFAULT_I2C_BUS_SDA (&pin_PA22) + +#define DEFAULT_SPI_BUS_SCK (&pin_PB11) +#define DEFAULT_SPI_BUS_MOSI (&pin_PB10) +#define DEFAULT_SPI_BUS_MISO (&pin_PA12) + +#define DEFAULT_UART_BUS_RX (&pin_PA11) +#define DEFAULT_UART_BUS_TX (&pin_PA10) diff --git a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk index 641611176f..a77da91f2c 100644 --- a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk @@ -5,6 +5,7 @@ USB_PRODUCT = "Feather M0" USB_MANUFACTURER = "Adafruit Industries LLC" INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = NONE CHIP_VARIANT = SAMD21G18A CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/feather_m0_basic/pins.c b/ports/atmel-samd/boards/feather_m0_basic/pins.c index c9119e77bc..4486d27ab4 100644 --- a/ports/atmel-samd/boards/feather_m0_basic/pins.c +++ b/ports/atmel-samd/boards/feather_m0_basic/pins.c @@ -1,4 +1,6 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, @@ -23,5 +25,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h index c85f553ba9..bfa8c642a2 100644 --- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h @@ -48,3 +48,13 @@ #include "external_flash/external_flash.h" #define BOARD_HAS_CRYSTAL 1 + +#define DEFAULT_I2C_BUS_SCL (&pin_PA23) +#define DEFAULT_I2C_BUS_SDA (&pin_PA22) + +#define DEFAULT_SPI_BUS_SCK (&pin_PB11) +#define DEFAULT_SPI_BUS_MOSI (&pin_PB10) +#define DEFAULT_SPI_BUS_MISO (&pin_PA12) + +#define DEFAULT_UART_BUS_RX (&pin_PA11) +#define DEFAULT_UART_BUS_TX (&pin_PA10) diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk index 909922dbe4..d4725fdf45 100644 --- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk @@ -5,6 +5,7 @@ USB_PRODUCT = "Feather M0 Express" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/feather_m0_express/pins.c b/ports/atmel-samd/boards/feather_m0_express/pins.c index c5c70ee5dc..68666c273e 100644 --- a/ports/atmel-samd/boards/feather_m0_express/pins.c +++ b/ports/atmel-samd/boards/feather_m0_express/pins.c @@ -1,4 +1,6 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, @@ -24,5 +26,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/board.c b/ports/atmel-samd/boards/feather_m0_express_crickit/board.c similarity index 74% rename from ports/atmel-samd/boards/metro_m4_express_revb/board.c rename to ports/atmel-samd/boards/feather_m0_express_crickit/board.c index a98385d295..c8e20206a1 100644 --- a/ports/atmel-samd/boards/metro_m4_express_revb/board.c +++ b/ports/atmel-samd/boards/feather_m0_express_crickit/board.c @@ -25,17 +25,9 @@ */ #include "boards/board.h" -#include "mpconfigboard.h" -#include "hal/include/hal_gpio.h" -void board_init(void) { - gpio_set_pin_function(MICROPY_HW_LED_TX, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_TX, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MICROPY_HW_LED_TX, true); - - gpio_set_pin_function(MICROPY_HW_LED_RX, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_RX, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MICROPY_HW_LED_RX, true); +void board_init(void) +{ } bool board_requests_safe_mode(void) { diff --git a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h new file mode 100644 index 0000000000..7564620136 --- /dev/null +++ b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h @@ -0,0 +1,60 @@ +#define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 Express with Crickit libraries" +#define MICROPY_HW_MCU_NAME "samd21g18" + +#define MICROPY_HW_NEOPIXEL (&pin_PA06) + +// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz. +#define SPI_FLASH_BAUDRATE (8000000) + +#define SPI_FLASH_MOSI_PIN PIN_PA08 +#define SPI_FLASH_MISO_PIN PIN_PA14 +#define SPI_FLASH_SCK_PIN PIN_PA09 +#define SPI_FLASH_CS_PIN PIN_PA13 +#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA08D_SERCOM2_PAD0 +#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA14C_SERCOM2_PAD2 +#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA09D_SERCOM2_PAD1 +#define SPI_FLASH_SERCOM SERCOM2 +#define SPI_FLASH_SERCOM_INDEX 2 +#define SPI_FLASH_MOSI_PAD 0 +#define SPI_FLASH_MISO_PAD 2 +#define SPI_FLASH_SCK_PAD 1 +// Transmit Data Pinout +// <0x0=>PAD[0,1]_DO_SCK +// <0x1=>PAD[2,3]_DO_SCK +// <0x2=>PAD[3,1]_DO_SCK +// <0x3=>PAD[0,3]_DO_SCK +#define SPI_FLASH_DOPO 0 +#define SPI_FLASH_DIPO 2 // same as MISO pad + +// These are pins not to reset. +#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_B ( 0 ) +#define MICROPY_PORT_C ( 0 ) + +#include "external_flash/external_flash.h" + +// If you change this, then make sure to update the linker scripts as well to +// make sure you don't overwrite code. +#define CIRCUITPY_INTERNAL_NVM_SIZE 256 + +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +#include "external_flash/devices.h" + +#define EXTERNAL_FLASH_DEVICE_COUNT 2 +#define EXTERNAL_FLASH_DEVICES S25FL216K, \ + GD25Q16C + +#include "external_flash/external_flash.h" + +#define BOARD_HAS_CRYSTAL 1 + +#define DEFAULT_I2C_BUS_SCL (&pin_PA23) +#define DEFAULT_I2C_BUS_SDA (&pin_PA22) + +#define DEFAULT_SPI_BUS_SCK (&pin_PB11) +#define DEFAULT_SPI_BUS_MOSI (&pin_PB10) +#define DEFAULT_SPI_BUS_MISO (&pin_PA12) + +#define DEFAULT_UART_BUS_RX (&pin_PA11) +#define DEFAULT_UART_BUS_TX (&pin_PA10) diff --git a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk new file mode 100644 index 0000000000..4096560c22 --- /dev/null +++ b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk @@ -0,0 +1,17 @@ +LD_FILE = boards/samd21x18-bootloader-external-flash.ld +USB_VID = 0x239A +USB_PID = 0x8023 +USB_PRODUCT = "Feather M0 Express" +USB_MANUFACTURER = "Adafruit Industries LLC" + +SPI_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ + +CHIP_VARIANT = SAMD21G18A +CHIP_FAMILY = samd21 + +# Include these Python libraries in firmware. +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Motor +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_seesaw diff --git a/ports/atmel-samd/boards/feather_m0_express_crickit/pins.c b/ports/atmel-samd/boards/feather_m0_express_crickit/pins.c new file mode 100644 index 0000000000..68666c273e --- /dev/null +++ b/ports/atmel-samd/boards/feather_m0_express_crickit/pins.c @@ -0,0 +1,33 @@ +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h index 33445940e6..4f4ea2ffea 100644 --- a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h @@ -13,3 +13,13 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) + +#define DEFAULT_I2C_BUS_SCL (&pin_PA23) +#define DEFAULT_I2C_BUS_SDA (&pin_PA22) + +#define DEFAULT_SPI_BUS_SCK (&pin_PB11) +#define DEFAULT_SPI_BUS_MOSI (&pin_PB10) +#define DEFAULT_SPI_BUS_MISO (&pin_PA12) + +#define DEFAULT_UART_BUS_RX (&pin_PA11) +#define DEFAULT_UART_BUS_TX (&pin_PA10) diff --git a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk index bf4f567af1..bd1a96479e 100644 --- a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk @@ -5,6 +5,7 @@ USB_PRODUCT = "Feather M0 RFM69" USB_MANUFACTURER = "Adafruit Industries LLC" INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = NONE CHIP_VARIANT = SAMD21G18A CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/feather_m0_rfm69/pins.c b/ports/atmel-samd/boards/feather_m0_rfm69/pins.c index eb5f531e36..6055f8a1b2 100644 --- a/ports/atmel-samd/boards/feather_m0_rfm69/pins.c +++ b/ports/atmel-samd/boards/feather_m0_rfm69/pins.c @@ -1,4 +1,6 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, @@ -26,5 +28,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_RFM69_D0), MP_ROM_PTR(&pin_PA09) }, { MP_ROM_QSTR(MP_QSTR_RFM69_RST), MP_ROM_PTR(&pin_PA08) }, { MP_ROM_QSTR(MP_QSTR_RFM69_CS), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h index a2563cc9f1..a9d586c2e3 100644 --- a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h @@ -13,3 +13,13 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) + +#define DEFAULT_I2C_BUS_SCL (&pin_PA23) +#define DEFAULT_I2C_BUS_SDA (&pin_PA22) + +#define DEFAULT_SPI_BUS_SCK (&pin_PB11) +#define DEFAULT_SPI_BUS_MOSI (&pin_PB10) +#define DEFAULT_SPI_BUS_MISO (&pin_PA12) + +#define DEFAULT_UART_BUS_RX (&pin_PA11) +#define DEFAULT_UART_BUS_TX (&pin_PA10) diff --git a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk index fbc422eef2..fedd8d0720 100644 --- a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk @@ -5,6 +5,7 @@ USB_PRODUCT = "Feather M0 RFM9x" USB_MANUFACTURER = "Adafruit Industries LLC" INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = NONE CHIP_VARIANT = SAMD21G18A CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/feather_m0_rfm9x/pins.c b/ports/atmel-samd/boards/feather_m0_rfm9x/pins.c index 2e5d0a8e68..7395c6e2f1 100644 --- a/ports/atmel-samd/boards/feather_m0_rfm9x/pins.c +++ b/ports/atmel-samd/boards/feather_m0_rfm9x/pins.c @@ -1,4 +1,6 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, @@ -26,5 +28,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_RFM9X_D0), MP_ROM_PTR(&pin_PA09) }, { MP_ROM_QSTR(MP_QSTR_RFM9X_RST), MP_ROM_PTR(&pin_PA08) }, { MP_ROM_QSTR(MP_QSTR_RFM9X_CS), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h index 5bc74d5a74..c8118e48b4 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h @@ -47,3 +47,13 @@ #define EXTERNAL_FLASH_DEVICES S25FL064L #include "external_flash/external_flash.h" + +#define DEFAULT_I2C_BUS_SCL (&pin_PA23) +#define DEFAULT_I2C_BUS_SDA (&pin_PA22) + +#define DEFAULT_SPI_BUS_SCK (&pin_PB11) +#define DEFAULT_SPI_BUS_MOSI (&pin_PB10) +#define DEFAULT_SPI_BUS_MISO (&pin_PA12) + +#define DEFAULT_UART_BUS_RX (&pin_PA11) +#define DEFAULT_UART_BUS_TX (&pin_PA10) diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk index 340421f500..79bf2d34a2 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk @@ -5,7 +5,7 @@ USB_PRODUCT = "Feather M0 Supersized" USB_MANUFACTURER = "Dave Astels" SPI_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A CHIP_FAMILY = samd21 - diff --git a/ports/atmel-samd/boards/feather_m0_supersized/pins.c b/ports/atmel-samd/boards/feather_m0_supersized/pins.c index c5c70ee5dc..68666c273e 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/pins.c +++ b/ports/atmel-samd/boards/feather_m0_supersized/pins.c @@ -1,4 +1,6 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, @@ -24,5 +26,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h index 6e10222562..b5af61ba6f 100644 --- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h @@ -3,15 +3,15 @@ #define CIRCUITPY_MCU_FAMILY samd51 -// This is for Rev C which is green +// Rev E -#define MICROPY_HW_NEOPIXEL (&pin_PB23) +#define MICROPY_HW_NEOPIXEL (&pin_PB03) // These are pins not to reset. -// QSPI Data pins and TX LED -#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09) -// RX LED, QSPI CS, QSPI SCK and NeoPixel pin -#define MICROPY_PORT_B (PORT_PB10 | PORT_PB11 | PORT_PB23 ) +// QSPI Data pins +#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11) +// QSPI CS, QSPI SCK and NeoPixel pin +#define MICROPY_PORT_B (PORT_PB03 | PORT_PB10 | PORT_PB11) #define MICROPY_PORT_C (0) #define MICROPY_PORT_D (0) @@ -25,9 +25,21 @@ #include "external_flash/devices.h" -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES W25Q16FW, GD25Q16C +#define EXTERNAL_FLASH_DEVICE_COUNT 1 +#define EXTERNAL_FLASH_DEVICES GD25Q16C #define EXTERNAL_FLASH_QSPI_DUAL #include "external_flash/external_flash.h" + +#define BOARD_HAS_CRYSTAL 1 + +#define DEFAULT_I2C_BUS_SCL (&pin_PA13) +#define DEFAULT_I2C_BUS_SDA (&pin_PA12) + +#define DEFAULT_SPI_BUS_SCK (&pin_PA17) +#define DEFAULT_SPI_BUS_MOSI (&pin_PB23) +#define DEFAULT_SPI_BUS_MISO (&pin_PB22) + +#define DEFAULT_UART_BUS_RX (&pin_PB17) +#define DEFAULT_UART_BUS_TX (&pin_PB16) diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk index 2bfd0f3a09..e19a27b88f 100644 --- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk @@ -5,6 +5,7 @@ USB_PRODUCT = "Feather M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" QSPI_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ -CHIP_VARIANT = SAMD51G19A +CHIP_VARIANT = SAMD51J19A CHIP_FAMILY = samd51 diff --git a/ports/atmel-samd/boards/feather_m4_express/pins.c b/ports/atmel-samd/boards/feather_m4_express/pins.c index c161e736ed..b9b04e0acf 100644 --- a/ports/atmel-samd/boards/feather_m4_express/pins.c +++ b/ports/atmel-samd/boards/feather_m4_express/pins.c @@ -1,30 +1,35 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) }, { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB08) }, { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PB09) }, - { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA06) }, - { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PA10) }, - { MP_ROM_QSTR(MP_QSTR_AREF), MP_ROM_PTR(&pin_PA03) }, - + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PA06) }, { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA17) }, - { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA19) }, - { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA18) }, - { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA07) }, - { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA07) }, - { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA04) }, - { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB23) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PB22) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PB17) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB17) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PB16) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB16) }, { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA12) }, { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA13) }, - { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA14) }, - { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA15) }, - { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA14) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA19) }, { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA20) }, { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA21) }, { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA22) }, { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA23) }, - { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB23) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB03) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PB01) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h index 6457d481f3..53e802f172 100644 --- a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h @@ -12,6 +12,57 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 +#define DEFAULT_I2C_BUS_SCL (&pin_PA05) +#define DEFAULT_I2C_BUS_SDA (&pin_PA04) + +#define DEFAULT_UART_BUS_RX (&pin_PA05) +#define DEFAULT_UART_BUS_TX (&pin_PA04) + #include "internal_flash.h" #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) + +#define IGNORE_PIN_PA03 1 +#define IGNORE_PIN_PA06 1 +#define IGNORE_PIN_PA07 1 +#define IGNORE_PIN_PA08 1 +#define IGNORE_PIN_PA09 1 +#define IGNORE_PIN_PA10 1 +#define IGNORE_PIN_PA11 1 +#define IGNORE_PIN_PA12 1 +#define IGNORE_PIN_PA13 1 +#define IGNORE_PIN_PA14 1 +#define IGNORE_PIN_PA15 1 +#define IGNORE_PIN_PA16 1 +#define IGNORE_PIN_PA17 1 +#define IGNORE_PIN_PA18 1 +#define IGNORE_PIN_PA19 1 +#define IGNORE_PIN_PA20 1 +#define IGNORE_PIN_PA21 1 +#define IGNORE_PIN_PA22 1 +#define IGNORE_PIN_PA27 1 +#define IGNORE_PIN_PA28 1 +#define IGNORE_PIN_PA30 1 +#define IGNORE_PIN_PA31 1 +#define IGNORE_PIN_PB01 1 +#define IGNORE_PIN_PB02 1 +#define IGNORE_PIN_PB03 1 +#define IGNORE_PIN_PB04 1 +#define IGNORE_PIN_PB05 1 +#define IGNORE_PIN_PB06 1 +#define IGNORE_PIN_PB07 1 +#define IGNORE_PIN_PB08 1 +#define IGNORE_PIN_PB09 1 +#define IGNORE_PIN_PB10 1 +#define IGNORE_PIN_PB11 1 +#define IGNORE_PIN_PB12 1 +#define IGNORE_PIN_PB13 1 +#define IGNORE_PIN_PB14 1 +#define IGNORE_PIN_PB15 1 +#define IGNORE_PIN_PB16 1 +#define IGNORE_PIN_PB17 1 +#define IGNORE_PIN_PB22 1 +#define IGNORE_PIN_PB23 1 +#define IGNORE_PIN_PB30 1 +#define IGNORE_PIN_PB31 1 +#define IGNORE_PIN_PB00 1 diff --git a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk index a406e8f58f..ddc4287c3f 100644 --- a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk +++ b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk @@ -5,6 +5,7 @@ USB_PRODUCT = "Gemma M0" USB_MANUFACTURER = "Adafruit Industries LLC" INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = NONE CHIP_VARIANT = SAMD21E18A CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/gemma_m0/pins.c b/ports/atmel-samd/boards/gemma_m0/pins.c index 5d3bedca0e..196e438e0b 100644 --- a/ports/atmel-samd/boards/gemma_m0/pins.c +++ b/ports/atmel-samd/boards/gemma_m0/pins.c @@ -1,4 +1,6 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) }, // pad 1 @@ -19,5 +21,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA00) }, { MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA01) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h index a7ecd27ea8..be59bc5d4a 100644 --- a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h @@ -46,3 +46,13 @@ GD25Q16C #include "external_flash/external_flash.h" + +#define DEFAULT_I2C_BUS_SCL (&pin_PA23) +#define DEFAULT_I2C_BUS_SDA (&pin_PA22) + +#define DEFAULT_SPI_BUS_SCK (&pin_PB11) +#define DEFAULT_SPI_BUS_MOSI (&pin_PB10) +#define DEFAULT_SPI_BUS_MISO (&pin_PA12) + +#define DEFAULT_UART_BUS_RX (&pin_PA11) +#define DEFAULT_UART_BUS_TX (&pin_PA10) diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk index 0fb0e38ed4..66586b6111 100644 --- a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk @@ -5,7 +5,7 @@ USB_PRODUCT = "Itsy Bitsy M0 Express" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A CHIP_FAMILY = samd21 - diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/pins.c b/ports/atmel-samd/boards/itsybitsy_m0_express/pins.c index b70bb6a76c..25407bc147 100644 --- a/ports/atmel-samd/boards/itsybitsy_m0_express/pins.c +++ b/ports/atmel-samd/boards/itsybitsy_m0_express/pins.c @@ -1,4 +1,6 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) }, @@ -38,5 +40,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA01) }, { MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA00) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h index 95c542a43e..faa0d6e754 100644 --- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h @@ -31,3 +31,13 @@ #define EXTERNAL_FLASH_DEVICES GD25Q16C #include "external_flash/external_flash.h" + +#define DEFAULT_I2C_BUS_SCL (&pin_PA13) +#define DEFAULT_I2C_BUS_SDA (&pin_PA12) + +#define DEFAULT_SPI_BUS_SCK (&pin_PA01) +#define DEFAULT_SPI_BUS_MOSI (&pin_PA00) +#define DEFAULT_SPI_BUS_MISO (&pin_PB23) + +#define DEFAULT_UART_BUS_RX (&pin_PA16) +#define DEFAULT_UART_BUS_TX (&pin_PA17) diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk index f96661327d..27f5ea2b88 100644 --- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk @@ -5,6 +5,7 @@ USB_PRODUCT = "ItsyBitsy M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" QSPI_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD51G19A CHIP_FAMILY = samd51 diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/pins.c b/ports/atmel-samd/boards/itsybitsy_m4_express/pins.c index 11aeda9c67..3997ecda42 100644 --- a/ports/atmel-samd/boards/itsybitsy_m4_express/pins.c +++ b/ports/atmel-samd/boards/itsybitsy_m4_express/pins.c @@ -1,4 +1,6 @@ -#include "samd51_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" // This mapping only includes functional names because pins broken // out on connectors are labeled with their MCU name available from @@ -27,13 +29,14 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA12) }, { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA13) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_AREF), MP_ROM_PTR(&pin_PA03) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA01) }, { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA00) }, { MP_OBJ_NEW_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PB23) }, { MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PB03) }, { MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h index e635acd593..f798c5d365 100644 --- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h @@ -49,3 +49,13 @@ #include "external_flash/external_flash.h" #define BOARD_HAS_CRYSTAL 1 + +#define DEFAULT_I2C_BUS_SCL (&pin_PA23) +#define DEFAULT_I2C_BUS_SDA (&pin_PA22) + +#define DEFAULT_SPI_BUS_SCK (&pin_PB11) +#define DEFAULT_SPI_BUS_MOSI (&pin_PB10) +#define DEFAULT_SPI_BUS_MISO (&pin_PA12) + +#define DEFAULT_UART_BUS_RX (&pin_PA11) +#define DEFAULT_UART_BUS_TX (&pin_PA10) diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk index 79d60380de..0388a408bc 100644 --- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk @@ -5,6 +5,7 @@ USB_PRODUCT = "Metro M0 Express" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/metro_m0_express/pins.c b/ports/atmel-samd/boards/metro_m0_express/pins.c index 58510faabb..13f0eb0ba2 100644 --- a/ports/atmel-samd/boards/metro_m0_express/pins.c +++ b/ports/atmel-samd/boards/metro_m0_express/pins.c @@ -1,4 +1,6 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, @@ -29,5 +31,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) }, { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) }, { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h index 7012037717..7aef929f7c 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h @@ -32,3 +32,15 @@ #define EXTERNAL_FLASH_DEVICES S25FL116K, S25FL216K, GD25Q16C #include "external_flash/external_flash.h" + +#define BOARD_HAS_CRYSTAL 1 + +#define DEFAULT_I2C_BUS_SCL (&pin_PB03) +#define DEFAULT_I2C_BUS_SDA (&pin_PB02) + +#define DEFAULT_SPI_BUS_SCK (&pin_PA13) +#define DEFAULT_SPI_BUS_MOSI (&pin_PA12) +#define DEFAULT_SPI_BUS_MISO (&pin_PA14) + +#define DEFAULT_UART_BUS_RX (&pin_PA23) +#define DEFAULT_UART_BUS_TX (&pin_PA22) diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk index 1d59ed9664..38e8a12d72 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk @@ -5,6 +5,7 @@ USB_PRODUCT = "Metro M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" QSPI_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD51J19A CHIP_FAMILY = samd51 diff --git a/ports/atmel-samd/boards/metro_m4_express/pins.c b/ports/atmel-samd/boards/metro_m4_express/pins.c index 32ecdf4923..0e66817f7c 100644 --- a/ports/atmel-samd/boards/metro_m4_express/pins.c +++ b/ports/atmel-samd/boards/metro_m4_express/pins.c @@ -1,4 +1,6 @@ -#include "samd51_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" // This mapping only includes functional names because pins broken // out on connectors are labeled with their MCU name available from @@ -31,8 +33,6 @@ STATIC const mp_map_elem_t board_global_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), (mp_obj_t)&pin_PB02 }, { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), (mp_obj_t)&pin_PB03 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_AREF), (mp_obj_t)&pin_PA03 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), (mp_obj_t)&pin_PB22 }, { MP_OBJ_NEW_QSTR(MP_QSTR_SCK), (mp_obj_t)&pin_PA13 }, @@ -41,5 +41,8 @@ STATIC const mp_map_elem_t board_global_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_LED_RX), (mp_obj_t)&pin_PB06 }, { MP_OBJ_NEW_QSTR(MP_QSTR_LED_TX), (mp_obj_t)&pin_PA27 }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h deleted file mode 100644 index 206d85465e..0000000000 --- a/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h +++ /dev/null @@ -1,62 +0,0 @@ -// This is for Rev B which a larger run was done and sent to Adafruit community -// members. - -#define MICROPY_HW_BOARD_NAME "Metro M4 Express Rev B (Black)" -#define MICROPY_HW_MCU_NAME "samd51j19" - -#define CIRCUITPY_MCU_FAMILY samd51 - -#define MICROPY_HW_LED_TX PIN_PA27 -#define MICROPY_HW_LED_RX PIN_PB06 - -#define MICROPY_HW_NEOPIXEL (&pin_PB17) - -#define SPI_FLASH_BAUDRATE (60000000) - -// Rev B: single channel SPI -// Rev C will be QSPI -#define SPI_FLASH_MOSI_PIN PIN_PB08 -#define SPI_FLASH_MISO_PIN PIN_PB11 -#define SPI_FLASH_SCK_PIN PIN_PB09 -#define SPI_FLASH_CS_PIN PIN_PB10 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PB08D_SERCOM4_PAD0 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PB11D_SERCOM4_PAD3 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PB09D_SERCOM4_PAD1 -#define SPI_FLASH_SERCOM SERCOM4 -#define SPI_FLASH_SERCOM_INDEX 4 -#define SPI_FLASH_MOSI_PAD 0 -#define SPI_FLASH_MISO_PAD 3 -#define SPI_FLASH_SCK_PAD 1 -// Transmit Data Pinout -// <0x0=>PAD[0,1]_DO_SCK -// <0x1=>PAD[2,3]_DO_SCK -// <0x2=>PAD[3,1]_DO_SCK -// <0x3=>PAD[0,3]_DO_SCK -#define SPI_FLASH_DOPO 0 -#define SPI_FLASH_DIPO 3 // same as MISO pad - -// These are pins not to reset. -// Pin for TX LED -#define MICROPY_PORT_A (PORT_PA27) -// Pins for RX LED, SPI flash and neopixel -#define MICROPY_PORT_B (PORT_PB06 | PORT_PB08 | PORT_PB09 | PORT_PB10 | PORT_PB11 | PORT_PB17) -#define MICROPY_PORT_C (0) -#define MICROPY_PORT_D (0) - -#define AUTORESET_DELAY_MS 500 - -#include "external_flash/external_flash.h" - -// If you change this, then make sure to update the linker scripts as well to -// make sure you don't overwrite code -#define CIRCUITPY_INTERNAL_NVM_SIZE 8192 - -#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) - -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES S25FL216K, \ - GD25Q16C - -#include "external_flash/external_flash.h" diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.mk deleted file mode 100644 index a3d6e25221..0000000000 --- a/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.mk +++ /dev/null @@ -1,10 +0,0 @@ -LD_FILE = boards/samd51x19-bootloader-external-flash.ld -USB_VID = 0x239A -USB_PID = 0x8021 -USB_PRODUCT = "Metro M4 Express Rev B (Black)" -USB_MANUFACTURER = "Adafruit Industries LLC" - -SPI_FLASH_FILESYSTEM = 1 - -CHIP_VARIANT = SAMD51J19A -CHIP_FAMILY = samd51 diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/pins.c b/ports/atmel-samd/boards/metro_m4_express_revb/pins.c deleted file mode 100644 index a18906f73d..0000000000 --- a/ports/atmel-samd/boards/metro_m4_express_revb/pins.c +++ /dev/null @@ -1,44 +0,0 @@ -#include "samd51_pins.h" - -// This mapping only includes functional names because pins broken -// out on connectors are labeled with their MCU name available from -// microcontroller.pin. -STATIC const mp_map_elem_t board_global_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR_A0), (mp_obj_t)&pin_PA02 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A1), (mp_obj_t)&pin_PA05 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A2), (mp_obj_t)&pin_PA06 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A3), (mp_obj_t)&pin_PA04 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A4), (mp_obj_t)&pin_PA11 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A5), (mp_obj_t)&pin_PA07 }, - - - { MP_OBJ_NEW_QSTR(MP_QSTR_D0), (mp_obj_t)&pin_PA23 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_RX), (mp_obj_t)&pin_PA23 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D1), (mp_obj_t)&pin_PA22 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_TX), (mp_obj_t)&pin_PA22 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D2), (mp_obj_t)&pin_PA08 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D3), (mp_obj_t)&pin_PA10 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D4), (mp_obj_t)&pin_PB12 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D5), (mp_obj_t)&pin_PB14 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D6), (mp_obj_t)&pin_PB15 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D7), (mp_obj_t)&pin_PA14 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D8), (mp_obj_t)&pin_PA16 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D9), (mp_obj_t)&pin_PA17 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D10), (mp_obj_t)&pin_PA18 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D11), (mp_obj_t)&pin_PA19 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D12), (mp_obj_t)&pin_PA20 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D13), (mp_obj_t)&pin_PA21 }, - - { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), (mp_obj_t)&pin_PB02 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), (mp_obj_t)&pin_PB03 }, - - { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), (mp_obj_t)&pin_PB17 }, - - { MP_OBJ_NEW_QSTR(MP_QSTR_SCK), (mp_obj_t)&pin_PA13 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), (mp_obj_t)&pin_PA12 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_MISO), (mp_obj_t)&pin_PA15 }, - - { MP_OBJ_NEW_QSTR(MP_QSTR_LED_RX), (mp_obj_t)&pin_PB06 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_LED_TX), (mp_obj_t)&pin_PA27 }, -}; -MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h index a26fd7fdd0..15979ae778 100644 --- a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h @@ -1,8 +1,8 @@ #define MICROPY_HW_BOARD_NAME "Adafruit pIRKey M0" #define MICROPY_HW_MCU_NAME "samd21e18" -// #define MICROPY_HW_APA102_MOSI (&pin_PA00) -// #define MICROPY_HW_APA102_SCK (&pin_PA01) +#define MICROPY_HW_APA102_MOSI (&pin_PA00) +#define MICROPY_HW_APA102_SCK (&pin_PA01) // #define CIRCUITPY_BITBANG_APA102 @@ -12,6 +12,58 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 +// A number of modules are removed for pIRKey to make room for frozen libraries. +#define PIRKEY_M0 (1) + #include "internal_flash.h" #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) + +#define IGNORE_PIN_PA02 1 +#define IGNORE_PIN_PA03 1 +#define IGNORE_PIN_PA04 1 +#define IGNORE_PIN_PA05 1 +#define IGNORE_PIN_PA06 1 +#define IGNORE_PIN_PA07 1 +#define IGNORE_PIN_PA08 1 +#define IGNORE_PIN_PA09 1 +#define IGNORE_PIN_PA10 1 +#define IGNORE_PIN_PA11 1 +#define IGNORE_PIN_PA12 1 +#define IGNORE_PIN_PA13 1 +#define IGNORE_PIN_PA14 1 +#define IGNORE_PIN_PA15 1 +#define IGNORE_PIN_PA16 1 +#define IGNORE_PIN_PA17 1 +#define IGNORE_PIN_PA18 1 +#define IGNORE_PIN_PA19 1 +#define IGNORE_PIN_PA20 1 +#define IGNORE_PIN_PA21 1 +#define IGNORE_PIN_PA22 1 +#define IGNORE_PIN_PA24 1 +#define IGNORE_PIN_PA25 1 +#define IGNORE_PIN_PA27 1 +#define IGNORE_PIN_PA30 1 +#define IGNORE_PIN_PA31 1 +#define IGNORE_PIN_PB00 1 +#define IGNORE_PIN_PB01 1 +#define IGNORE_PIN_PB02 1 +#define IGNORE_PIN_PB03 1 +#define IGNORE_PIN_PB04 1 +#define IGNORE_PIN_PB05 1 +#define IGNORE_PIN_PB06 1 +#define IGNORE_PIN_PB07 1 +#define IGNORE_PIN_PB08 1 +#define IGNORE_PIN_PB09 1 +#define IGNORE_PIN_PB10 1 +#define IGNORE_PIN_PB11 1 +#define IGNORE_PIN_PB12 1 +#define IGNORE_PIN_PB13 1 +#define IGNORE_PIN_PB14 1 +#define IGNORE_PIN_PB15 1 +#define IGNORE_PIN_PB16 1 +#define IGNORE_PIN_PB17 1 +#define IGNORE_PIN_PB22 1 +#define IGNORE_PIN_PB23 1 +#define IGNORE_PIN_PB30 1 +#define IGNORE_PIN_PB31 1 diff --git a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk index 52dfc14309..0f8d0f9ca4 100644 --- a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk +++ b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk @@ -5,6 +5,12 @@ USB_PRODUCT = "pIRKey M0" USB_MANUFACTURER = "Adafruit Industries LLC" INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = NONE CHIP_VARIANT = SAMD21E18A CHIP_FAMILY = samd21 + +# Include these Python libraries in firmware. +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DotStar +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_IRRemote diff --git a/ports/atmel-samd/boards/pirkey_m0/pins.c b/ports/atmel-samd/boards/pirkey_m0/pins.c index a1b7db85c8..e08302f140 100644 --- a/ports/atmel-samd/boards/pirkey_m0/pins.c +++ b/ports/atmel-samd/boards/pirkey_m0/pins.c @@ -1,9 +1,14 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_REMOTEIN), MP_ROM_PTR(&pin_PA28) }, { MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA00) }, { MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA01) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h index 05033ad38b..d561947e39 100644 --- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h @@ -14,3 +14,55 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) + +#define IGNORE_PIN_PA03 1 +#define IGNORE_PIN_PA04 1 +#define IGNORE_PIN_PA11 1 +#define IGNORE_PIN_PA12 1 +#define IGNORE_PIN_PA13 1 +#define IGNORE_PIN_PA14 1 +#define IGNORE_PIN_PA15 1 +#define IGNORE_PIN_PA16 1 +#define IGNORE_PIN_PA17 1 +#define IGNORE_PIN_PA18 1 +#define IGNORE_PIN_PA19 1 +#define IGNORE_PIN_PA20 1 +#define IGNORE_PIN_PA21 1 +#define IGNORE_PIN_PA22 1 +#define IGNORE_PIN_PA23 1 +#define IGNORE_PIN_PA27 1 +#define IGNORE_PIN_PA28 1 +#define IGNORE_PIN_PA30 1 +#define IGNORE_PIN_PA31 1 +#define IGNORE_PIN_PB01 1 +#define IGNORE_PIN_PB02 1 +#define IGNORE_PIN_PB03 1 +#define IGNORE_PIN_PB04 1 +#define IGNORE_PIN_PB05 1 +#define IGNORE_PIN_PB06 1 +#define IGNORE_PIN_PB07 1 +#define IGNORE_PIN_PB08 1 +#define IGNORE_PIN_PB09 1 +#define IGNORE_PIN_PB10 1 +#define IGNORE_PIN_PB11 1 +#define IGNORE_PIN_PB12 1 +#define IGNORE_PIN_PB13 1 +#define IGNORE_PIN_PB14 1 +#define IGNORE_PIN_PB15 1 +#define IGNORE_PIN_PB16 1 +#define IGNORE_PIN_PB17 1 +#define IGNORE_PIN_PB22 1 +#define IGNORE_PIN_PB23 1 +#define IGNORE_PIN_PB30 1 +#define IGNORE_PIN_PB31 1 +#define IGNORE_PIN_PB00 1 + +#define DEFAULT_I2C_BUS_SCL (&pin_PA09) +#define DEFAULT_I2C_BUS_SDA (&pin_PA08) + +#define DEFAULT_SPI_BUS_SCK (&pin_PA07) +#define DEFAULT_SPI_BUS_MOSI (&pin_PA06) +#define DEFAULT_SPI_BUS_MISO (&pin_PA09) + +#define DEFAULT_UART_BUS_RX (&pin_PA07) +#define DEFAULT_UART_BUS_TX (&pin_PA06) diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk index 43d07eb5ff..c9c45152be 100644 --- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk +++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk @@ -5,6 +5,7 @@ USB_PRODUCT = "Trinket M0" USB_MANUFACTURER = "Adafruit Industries LLC" INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = NONE CHIP_VARIANT = SAMD21E18A CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/trinket_m0/pins.c b/ports/atmel-samd/boards/trinket_m0/pins.c index ac58986009..6330170249 100644 --- a/ports/atmel-samd/boards/trinket_m0/pins.c +++ b/ports/atmel-samd/boards/trinket_m0/pins.c @@ -1,4 +1,6 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA08) }, @@ -27,5 +29,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA00) }, { MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA01) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h index ea45c1f8b8..3377d1b7ea 100644 --- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h +++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h @@ -54,3 +54,13 @@ #define EXTERNAL_FLASH_DEVICES W25Q32BV #include "external_flash/external_flash.h" + +#define DEFAULT_I2C_BUS_SCL (&pin_PA09) +#define DEFAULT_I2C_BUS_SDA (&pin_PA08) + +#define DEFAULT_SPI_BUS_SCK (&pin_PA07) +#define DEFAULT_SPI_BUS_MOSI (&pin_PA06) +#define DEFAULT_SPI_BUS_MISO (&pin_PA09) + +#define DEFAULT_UART_BUS_RX (&pin_PA07) +#define DEFAULT_UART_BUS_TX (&pin_PA06) diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk index a904b2837c..d97aa08ab4 100644 --- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk +++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk @@ -5,6 +5,7 @@ USB_PRODUCT="Trinket M0 Haxpress" USB_MANUFACTURER="Radomir Dopieralski" SPI_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21E18A CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/pins.c b/ports/atmel-samd/boards/trinket_m0_haxpress/pins.c index ac58986009..6330170249 100644 --- a/ports/atmel-samd/boards/trinket_m0_haxpress/pins.c +++ b/ports/atmel-samd/boards/trinket_m0_haxpress/pins.c @@ -1,4 +1,6 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA08) }, @@ -27,5 +29,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA00) }, { MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA01) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.h b/ports/atmel-samd/boards/ugame10/mpconfigboard.h index 1652314ed8..4e5e885694 100644 --- a/ports/atmel-samd/boards/ugame10/mpconfigboard.h +++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.h @@ -47,3 +47,8 @@ #define EXTERNAL_FLASH_DEVICES S25FL216K #include "external_flash/external_flash.h" + +#define EXTRA_BUILTIN_MODULES \ + { MP_OBJ_NEW_QSTR(MP_QSTR_audioio), (mp_obj_t)&audioio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR__stage), (mp_obj_t)&stage_module } diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk index 343115fbb4..2386531f91 100644 --- a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk +++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk @@ -6,6 +6,10 @@ USB_PRODUCT = "uGame10" USB_MANUFACTURER = "Radomir Dopieralski" SPI_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21E18A CHIP_FAMILY = samd21 + + +FROZEN_MPY_DIRS += $(TOP)/frozen/ugame10 diff --git a/ports/atmel-samd/boards/ugame10/pins.c b/ports/atmel-samd/boards/ugame10/pins.c index af516a401d..87ace5e96f 100644 --- a/ports/atmel-samd/boards/ugame10/pins.c +++ b/ports/atmel-samd/boards/ugame10/pins.c @@ -1,4 +1,6 @@ -#include "samd21_pins.h" +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_X), MP_ROM_PTR(&pin_PA00) }, @@ -23,5 +25,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_B), MP_ROM_PTR(&pin_PA14) }, { MP_ROM_QSTR(MP_QSTR_C), MP_ROM_PTR(&pin_PA15) }, { MP_ROM_QSTR(MP_QSTR_D), MP_ROM_PTR(&pin_PA28) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/common-hal/analogio/AnalogIn.c b/ports/atmel-samd/common-hal/analogio/AnalogIn.c index 02613ae078..e452eb0305 100644 --- a/ports/atmel-samd/common-hal/analogio/AnalogIn.c +++ b/ports/atmel-samd/common-hal/analogio/AnalogIn.c @@ -34,7 +34,7 @@ #include "py/binary.h" #include "py/mphal.h" -#include "peripherals.h" +#include "peripherals/adc.h" #include "shared-bindings/analogio/AnalogIn.h" #include "atmel_start_pins.h" diff --git a/ports/atmel-samd/common-hal/analogio/AnalogOut.c b/ports/atmel-samd/common-hal/analogio/AnalogOut.c index 97299a8634..9ceca38683 100644 --- a/ports/atmel-samd/common-hal/analogio/AnalogOut.c +++ b/ports/atmel-samd/common-hal/analogio/AnalogOut.c @@ -42,10 +42,6 @@ #include "hpl/pm/hpl_pm_base.h" #endif -#ifdef SAMD51 -#include "samd51_pins.h" -#endif - void common_hal_analogio_analogout_construct(analogio_analogout_obj_t* self, const mcu_pin_obj_t *pin) { if (pin->pin != PIN_PA02 @@ -73,7 +69,7 @@ void common_hal_analogio_analogout_construct(analogio_analogout_obj_t* self, #endif // SAMD21: This clock should be <= 12 MHz, per datasheet section 47.6.3. - // SAMD51: This clock should be <= 350kHz, per datasheet table 37-6. + // SAMD51: This clock should be <= 350kHz, per datasheet table 37-6. _gclk_enable_channel(DAC_GCLK_ID, CONF_GCLK_DAC_SRC); // Don't double init the DAC on the SAMD51 when both outputs are in use. We use the free state diff --git a/ports/atmel-samd/common-hal/audiobusio/I2SOut.c b/ports/atmel-samd/common-hal/audiobusio/I2SOut.c index f4a8eb52e8..27a7b9ee04 100644 --- a/ports/atmel-samd/common-hal/audiobusio/I2SOut.c +++ b/ports/atmel-samd/common-hal/audiobusio/I2SOut.c @@ -45,13 +45,14 @@ #include "hpl/pm/hpl_pm_base.h" #endif +#include "peripherals/clocks.h" +#include "peripherals/dma.h" +#include "peripherals/events.h" +#include "peripherals/i2s.h" +#include "peripherals/pins.h" +#include "peripherals/timers.h" + #include "audio_dma.h" -#include "clocks.h" -#include "events.h" -#include "i2s.h" -#include "pins.h" -#include "shared_dma.h" -#include "timers.h" #ifdef SAMD21 #define SERCTRL(name) I2S_SERCTRL_ ## name diff --git a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c index 44129eed12..5502fcd812 100644 --- a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c +++ b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -41,12 +41,13 @@ #include "hal/include/hal_gpio.h" #include "hal/utils/include/utils.h" +#include "peripherals/clocks.h" +#include "peripherals/events.h" +#include "peripherals/i2s.h" +#include "peripherals/pins.h" +#include "peripherals/dma.h" + #include "audio_dma.h" -#include "clocks.h" -#include "events.h" -#include "i2s.h" -#include "pins.h" -#include "shared_dma.h" #include "tick.h" #define OVERSAMPLING 64 diff --git a/ports/atmel-samd/common-hal/audioio/AudioOut.c b/ports/atmel-samd/common-hal/audioio/AudioOut.c index 6971c020b4..fc5c756731 100644 --- a/ports/atmel-samd/common-hal/audioio/AudioOut.c +++ b/ports/atmel-samd/common-hal/audioio/AudioOut.c @@ -45,10 +45,11 @@ #endif #include "audio_dma.h" -#include "events.h" -#include "samd21_pins.h" -#include "shared_dma.h" -#include "timers.h" + +#include "peripherals/dma.h" +#include "peripherals/events.h" +#include "peripherals/pins.h" +#include "peripherals/timers.h" void audioout_reset(void) { } @@ -240,6 +241,8 @@ void common_hal_audioio_audioout_deinit(audioio_audioout_obj_t* self) { disable_event_channel(self->tc_to_dac_event_channel); + tc_set_enable(tc_insts[self->tc_index], false); + reset_pin(self->left_channel->pin); self->left_channel = mp_const_none; #ifdef SAMD51 diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c index 77676b5355..c14b2d68f0 100644 --- a/ports/atmel-samd/common-hal/busio/I2C.c +++ b/ports/atmel-samd/common-hal/busio/I2C.c @@ -32,8 +32,7 @@ #include "hal/include/hal_i2c_m_sync.h" #include "hal/include/hpl_i2c_m_sync.h" -#include "peripherals.h" -#include "pins.h" +#include "peripherals/sercom.h" #include "shared-bindings/microcontroller/__init__.h" @@ -41,7 +40,11 @@ #define ATTEMPTS 2 void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, - const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t frequency) { + const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t frequency, uint32_t timeout) { + #ifdef PIRKEY_M0 + mp_raise_NotImplementedError("Not enough pins available"); + return; + #endif Sercom* sercom = NULL; uint8_t sercom_index; uint32_t sda_pinmux = 0; diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index a2bf30f054..a9bd559039 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -36,9 +36,8 @@ #include "hal/include/hpl_spi_m_sync.h" #include "supervisor/shared/rgb_led_status.h" -#include "peripherals.h" -#include "pins.h" -#include "shared_dma.h" +#include "peripherals/dma.h" +#include "peripherals/sercom.h" void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c index 5376775206..a95ccf3acc 100644 --- a/ports/atmel-samd/common-hal/busio/UART.c +++ b/ports/atmel-samd/common-hal/busio/UART.c @@ -42,8 +42,7 @@ #include "hal/include/hal_usart_async.h" #include "hal/include/hpl_usart_async.h" -#include "peripherals.h" -#include "pins.h" +#include "peripherals/sercom.h" // Do-nothing callback needed so that usart_async code will enable rx interrupts. // See comment below re usart_async_register_callback() diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.c b/ports/atmel-samd/common-hal/microcontroller/Pin.c index e1ca5d6223..ad97581e14 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Pin.c +++ b/ports/atmel-samd/common-hal/microcontroller/Pin.c @@ -29,13 +29,8 @@ #include "atmel_start_pins.h" #include "hal/include/hal_gpio.h" +#include "peripherals/pins.h" #include "supervisor/shared/rgb_led_status.h" -#ifdef SAMD21 -#include "samd21_pins.h" -#endif -#ifdef SAMD51 -#include "samd51_pins.h" -#endif #ifdef MICROPY_HW_NEOPIXEL bool neopixel_in_use; diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.h b/ports/atmel-samd/common-hal/microcontroller/Pin.h index 4e21a14cd8..4230246a5a 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Pin.h +++ b/ports/atmel-samd/common-hal/microcontroller/Pin.h @@ -81,4 +81,6 @@ void reset_all_pins(void); void reset_pin(uint8_t pin); void claim_pin(const mcu_pin_obj_t* pin); +#include "peripherals/pins.h" + #endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_PIN_H diff --git a/ports/atmel-samd/common-hal/microcontroller/Processor.c b/ports/atmel-samd/common-hal/microcontroller/Processor.c index e7f758cd10..a76ee2e78c 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Processor.c +++ b/ports/atmel-samd/common-hal/microcontroller/Processor.c @@ -63,7 +63,7 @@ #include "common-hal/microcontroller/Processor.h" -#include "peripherals.h" +#include "peripherals/adc.h" #include "peripheral_clk_config.h" diff --git a/ports/atmel-samd/common-hal/microcontroller/__init__.c b/ports/atmel-samd/common-hal/microcontroller/__init__.c index 4b8c33182f..c57b6939ce 100644 --- a/ports/atmel-samd/common-hal/microcontroller/__init__.c +++ b/ports/atmel-samd/common-hal/microcontroller/__init__.c @@ -30,10 +30,10 @@ #include "py/runtime.h" #include "reset.h" -#include "samd21_pins.h" #include "shared-bindings/nvm/ByteArray.h" #include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Processor.h" void common_hal_mcu_delay_us(uint32_t delay) { @@ -42,13 +42,31 @@ void common_hal_mcu_delay_us(uint32_t delay) { // Interrupt flags that will be saved and restored during disable/Enable // interrupt functions below. -volatile hal_atomic_t flags; + +// ASF4's interrupt disable doesn't handle duplicate calls +volatile uint32_t interrupt_flags; +volatile uint32_t nesting_count = 0; void common_hal_mcu_disable_interrupts(void) { - atomic_enter_critical(&flags); + if (nesting_count == 0) { + interrupt_flags = __get_PRIMASK(); + __disable_irq(); + __DMB(); + } + nesting_count++; } void common_hal_mcu_enable_interrupts(void) { - atomic_leave_critical(&flags); + if (nesting_count == 0) { + // This is very very bad because it means there was mismatched disable/enables so we + // "HardFault". + HardFault_Handler(); + } + nesting_count--; + if (nesting_count > 0) { + return; + } + __DMB(); + __set_PRIMASK(interrupt_flags); } extern uint32_t _ezero; @@ -97,162 +115,162 @@ const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = { // This maps MCU pin names to pin objects. STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { // Pins in datasheet order. -#ifdef PIN_PA00 +#if defined(PIN_PA00) && !defined(IGNORE_PIN_PA00) { MP_ROM_QSTR(MP_QSTR_PA00), MP_ROM_PTR(&pin_PA00) }, #endif -#ifdef PIN_PA01 +#if defined(PIN_PA01) && !defined(IGNORE_PIN_PA01) { MP_ROM_QSTR(MP_QSTR_PA01), MP_ROM_PTR(&pin_PA01) }, #endif -#ifdef PIN_PA02 +#if defined(PIN_PA02) && !defined(IGNORE_PIN_PA02) { MP_ROM_QSTR(MP_QSTR_PA02), MP_ROM_PTR(&pin_PA02) }, #endif -#ifdef PIN_PA03 +#if defined(PIN_PA03) && !defined(IGNORE_PIN_PA03) { MP_ROM_QSTR(MP_QSTR_PA03), MP_ROM_PTR(&pin_PA03) }, #endif -#ifdef PIN_PB04 +#if defined(PIN_PB04) && !defined(IGNORE_PIN_PB04) { MP_ROM_QSTR(MP_QSTR_PB04), MP_ROM_PTR(&pin_PB04) }, #endif -#ifdef PIN_PB05 +#if defined(PIN_PB05) && !defined(IGNORE_PIN_PB05) { MP_ROM_QSTR(MP_QSTR_PB05), MP_ROM_PTR(&pin_PB05) }, #endif -#ifdef PIN_PB06 +#if defined(PIN_PB06) && !defined(IGNORE_PIN_PB06) { MP_ROM_QSTR(MP_QSTR_PB06), MP_ROM_PTR(&pin_PB06) }, #endif -#ifdef PIN_PB07 +#if defined(PIN_PB07) && !defined(IGNORE_PIN_PB07) { MP_ROM_QSTR(MP_QSTR_PB07), MP_ROM_PTR(&pin_PB07) }, #endif -#ifdef PIN_PB08 +#if defined(PIN_PB08) && !defined(IGNORE_PIN_PB08) { MP_ROM_QSTR(MP_QSTR_PB08), MP_ROM_PTR(&pin_PB08) }, #endif -#ifdef PIN_PB09 +#if defined(PIN_PB09) && !defined(IGNORE_PIN_PB09) { MP_ROM_QSTR(MP_QSTR_PB09), MP_ROM_PTR(&pin_PB09) }, #endif -#ifdef PIN_PA04 +#if defined(PIN_PA04) && !defined(IGNORE_PIN_PA04) { MP_ROM_QSTR(MP_QSTR_PA04), MP_ROM_PTR(&pin_PA04) }, #endif -#ifdef PIN_PA05 +#if defined(PIN_PA05) && !defined(IGNORE_PIN_PA05) { MP_ROM_QSTR(MP_QSTR_PA05), MP_ROM_PTR(&pin_PA05) }, #endif -#ifdef PIN_PA06 +#if defined(PIN_PA06) && !defined(IGNORE_PIN_PA06) { MP_ROM_QSTR(MP_QSTR_PA06), MP_ROM_PTR(&pin_PA06) }, #endif -#ifdef PIN_PA07 +#if defined(PIN_PA07) && !defined(IGNORE_PIN_PA07) { MP_ROM_QSTR(MP_QSTR_PA07), MP_ROM_PTR(&pin_PA07) }, #endif -#ifdef PIN_PA08 +#if defined(PIN_PA08) && !defined(IGNORE_PIN_PA08) { MP_ROM_QSTR(MP_QSTR_PA08), MP_ROM_PTR(&pin_PA08) }, #endif -#ifdef PIN_PA09 +#if defined(PIN_PA09) && !defined(IGNORE_PIN_PA09) { MP_ROM_QSTR(MP_QSTR_PA09), MP_ROM_PTR(&pin_PA09) }, #endif -#ifdef PIN_PA10 +#if defined(PIN_PA10) && !defined(IGNORE_PIN_PA10) { MP_ROM_QSTR(MP_QSTR_PA10), MP_ROM_PTR(&pin_PA10) }, #endif -#ifdef PIN_PA11 +#if defined(PIN_PA11) && !defined(IGNORE_PIN_PA11) { MP_ROM_QSTR(MP_QSTR_PA11), MP_ROM_PTR(&pin_PA11) }, #endif -#ifdef PIN_PB10 +#if defined(PIN_PB10) && !defined(IGNORE_PIN_PB10) { MP_ROM_QSTR(MP_QSTR_PB10), MP_ROM_PTR(&pin_PB10) }, #endif -#ifdef PIN_PB11 +#if defined(PIN_PB11) && !defined(IGNORE_PIN_PB11) { MP_ROM_QSTR(MP_QSTR_PB11), MP_ROM_PTR(&pin_PB11) }, #endif -#ifdef PIN_PB12 +#if defined(PIN_PB12) && !defined(IGNORE_PIN_PB12) { MP_ROM_QSTR(MP_QSTR_PB12), MP_ROM_PTR(&pin_PB12) }, #endif -#ifdef PIN_PB13 +#if defined(PIN_PB13) && !defined(IGNORE_PIN_PB13) { MP_ROM_QSTR(MP_QSTR_PB13), MP_ROM_PTR(&pin_PB13) }, #endif -#ifdef PIN_PB14 +#if defined(PIN_PB14) && !defined(IGNORE_PIN_PB14) { MP_ROM_QSTR(MP_QSTR_PB14), MP_ROM_PTR(&pin_PB14) }, #endif // Second page. -#ifdef PIN_PB15 +#if defined(PIN_PB15) && !defined(IGNORE_PIN_PB15) { MP_ROM_QSTR(MP_QSTR_PB15), MP_ROM_PTR(&pin_PB15) }, #endif -#ifdef PIN_PA12 +#if defined(PIN_PA12) && !defined(IGNORE_PIN_PA12) { MP_ROM_QSTR(MP_QSTR_PA12), MP_ROM_PTR(&pin_PA12) }, #endif -#ifdef PIN_PA13 +#if defined(PIN_PA13) && !defined(IGNORE_PIN_PA13) { MP_ROM_QSTR(MP_QSTR_PA13), MP_ROM_PTR(&pin_PA13) }, #endif -#ifdef PIN_PA14 +#if defined(PIN_PA14) && !defined(IGNORE_PIN_PA14) { MP_ROM_QSTR(MP_QSTR_PA14), MP_ROM_PTR(&pin_PA14) }, #endif -#ifdef PIN_PA15 +#if defined(PIN_PA15) && !defined(IGNORE_PIN_PA15) { MP_ROM_QSTR(MP_QSTR_PA15), MP_ROM_PTR(&pin_PA15) }, #endif -#ifdef PIN_PA16 +#if defined(PIN_PA16) && !defined(IGNORE_PIN_PA16) { MP_ROM_QSTR(MP_QSTR_PA16), MP_ROM_PTR(&pin_PA16) }, #endif -#ifdef PIN_PA17 +#if defined(PIN_PA17) && !defined(IGNORE_PIN_PA17) { MP_ROM_QSTR(MP_QSTR_PA17), MP_ROM_PTR(&pin_PA17) }, #endif -#ifdef PIN_PA18 +#if defined(PIN_PA18) && !defined(IGNORE_PIN_PA18) { MP_ROM_QSTR(MP_QSTR_PA18), MP_ROM_PTR(&pin_PA18) }, #endif -#ifdef PIN_PA19 +#if defined(PIN_PA19) && !defined(IGNORE_PIN_PA19) { MP_ROM_QSTR(MP_QSTR_PA19), MP_ROM_PTR(&pin_PA19) }, #endif -#ifdef PIN_PB16 +#if defined(PIN_PB16) && !defined(IGNORE_PIN_PB16) { MP_ROM_QSTR(MP_QSTR_PB16), MP_ROM_PTR(&pin_PB16) }, #endif -#ifdef PIN_PB17 +#if defined(PIN_PB17) && !defined(IGNORE_PIN_PB17) { MP_ROM_QSTR(MP_QSTR_PB17), MP_ROM_PTR(&pin_PB17) }, #endif -#ifdef PIN_PA20 +#if defined(PIN_PA20) && !defined(IGNORE_PIN_PA20) { MP_ROM_QSTR(MP_QSTR_PA20), MP_ROM_PTR(&pin_PA20) }, #endif -#ifdef PIN_PA21 +#if defined(PIN_PA21) && !defined(IGNORE_PIN_PA21) { MP_ROM_QSTR(MP_QSTR_PA21), MP_ROM_PTR(&pin_PA21) }, #endif -#ifdef PIN_PA22 +#if defined(PIN_PA22) && !defined(IGNORE_PIN_PA22) { MP_ROM_QSTR(MP_QSTR_PA22), MP_ROM_PTR(&pin_PA22) }, #endif -#ifdef PIN_PA23 +#if defined(PIN_PA23) && !defined(IGNORE_PIN_PA23) { MP_ROM_QSTR(MP_QSTR_PA23), MP_ROM_PTR(&pin_PA23) }, #endif -#ifdef PIN_PA24 +#if defined(PIN_PA24) && !defined(IGNORE_PIN_PA24) { MP_ROM_QSTR(MP_QSTR_PA24), MP_ROM_PTR(&pin_PA24) }, #endif -#ifdef PIN_PA25 +#if defined(PIN_PA25) && !defined(IGNORE_PIN_PA25) { MP_ROM_QSTR(MP_QSTR_PA25), MP_ROM_PTR(&pin_PA25) }, #endif -#ifdef PIN_PB22 +#if defined(PIN_PB22) && !defined(IGNORE_PIN_PB22) { MP_ROM_QSTR(MP_QSTR_PB22), MP_ROM_PTR(&pin_PB22) }, #endif -#ifdef PIN_PB23 +#if defined(PIN_PB23) && !defined(IGNORE_PIN_PB23) { MP_ROM_QSTR(MP_QSTR_PB23), MP_ROM_PTR(&pin_PB23) }, #endif -#ifdef PIN_PA27 +#if defined(PIN_PA27) && !defined(IGNORE_PIN_PA27) { MP_ROM_QSTR(MP_QSTR_PA27), MP_ROM_PTR(&pin_PA27) }, #endif -#ifdef PIN_PA28 +#if defined(PIN_PA28) && !defined(IGNORE_PIN_PA28) { MP_ROM_QSTR(MP_QSTR_PA28), MP_ROM_PTR(&pin_PA28) }, #endif -#ifdef PIN_PA30 +#if defined(PIN_PA30) && !defined(IGNORE_PIN_PA30) { MP_ROM_QSTR(MP_QSTR_PA30), MP_ROM_PTR(&pin_PA30) }, #endif -#ifdef PIN_PA31 +#if defined(PIN_PA31) && !defined(IGNORE_PIN_PA31) { MP_ROM_QSTR(MP_QSTR_PA31), MP_ROM_PTR(&pin_PA31) }, #endif -#ifdef PIN_PB30 +#if defined(PIN_PB30) && !defined(IGNORE_PIN_PB30) { MP_ROM_QSTR(MP_QSTR_PB30), MP_ROM_PTR(&pin_PB30) }, #endif -#ifdef PIN_PB31 +#if defined(PIN_PB31) && !defined(IGNORE_PIN_PB31) { MP_ROM_QSTR(MP_QSTR_PB31), MP_ROM_PTR(&pin_PB31) }, #endif -#ifdef PIN_PB00 +#if defined(PIN_PB00) && !defined(IGNORE_PIN_PB00) { MP_ROM_QSTR(MP_QSTR_PB00), MP_ROM_PTR(&pin_PB00) }, #endif -#ifdef PIN_PB01 +#if defined(PIN_PB01) && !defined(IGNORE_PIN_PB01) { MP_ROM_QSTR(MP_QSTR_PB01), MP_ROM_PTR(&pin_PB01) }, #endif -#ifdef PIN_PB02 +#if defined(PIN_PB02) && !defined(IGNORE_PIN_PB02) { MP_ROM_QSTR(MP_QSTR_PB02), MP_ROM_PTR(&pin_PB02) }, #endif -#ifdef PIN_PB03 +#if defined(PIN_PB03) && !defined(IGNORE_PIN_PB03) { MP_ROM_QSTR(MP_QSTR_PB03), MP_ROM_PTR(&pin_PB03) } #endif }; diff --git a/ports/atmel-samd/common-hal/pulseio/PWMOut.c b/ports/atmel-samd/common-hal/pulseio/PWMOut.c index 24cd154c2a..18d896686a 100644 --- a/ports/atmel-samd/common-hal/pulseio/PWMOut.c +++ b/ports/atmel-samd/common-hal/pulseio/PWMOut.c @@ -34,9 +34,9 @@ #include "atmel_start_pins.h" #include "hal/utils/include/utils_repeat_macro.h" -#include "timers.h" +#include "peripherals/timers.h" -#include "samd21_pins.h" +#include "peripherals/pins.h" #undef ENABLE diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.c b/ports/atmel-samd/common-hal/pulseio/PulseIn.c index 6e3aa3abb3..99a60a8297 100644 --- a/ports/atmel-samd/common-hal/pulseio/PulseIn.c +++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2017-2018 Scott Shawcroft for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,90 +34,28 @@ #include "mpconfigport.h" #include "py/gc.h" #include "py/runtime.h" -#include "samd21_pins.h" +#include "peripherals/external_interrupts.h" +#include "peripherals/pins.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/pulseio/PulseIn.h" -#ifdef SAMD21 -#include "hpl/gclk/hpl_gclk_base.h" -#endif - #include "tick.h" -static pulseio_pulsein_obj_t *active_pulseins[EIC_EXTINT_NUM]; -static uint64_t last_ms[EIC_EXTINT_NUM]; -static uint16_t last_us[EIC_EXTINT_NUM]; - -bool eic_get_enable(void) { - #ifdef SAMD51 - return EIC->CTRLA.bit.ENABLE; - #endif - #ifdef SAMD21 - return EIC->CTRL.bit.ENABLE; - #endif -} - -void eic_set_enable(bool value) { - #ifdef SAMD51 - EIC->CTRLA.bit.ENABLE = value; - while (EIC->SYNCBUSY.bit.ENABLE != 0) {} - // This won't actually block long enough in Rev A of SAMD51 and will miss edges in the first - // three cycles of the peripheral clock. See the errata for details. It shouldn't impact us. - #endif - #ifdef SAMD21 - EIC->CTRL.bit.ENABLE = value; - while (EIC->STATUS.bit.SYNCBUSY != 0) {} - #endif -} - -void eic_reset(void) { - #ifdef SAMD51 - EIC->CTRLA.bit.SWRST = true; - while (EIC->SYNCBUSY.bit.SWRST != 0) {} - // This won't actually block long enough in Rev A of SAMD51 and will miss edges in the first - // three cycles of the peripheral clock. See the errata for details. It shouldn't impact us. - #endif - #ifdef SAMD21 - EIC->CTRL.bit.SWRST = true; - while (EIC->STATUS.bit.SYNCBUSY != 0) {} - #endif -} - -void pulsein_reset(void) { - for (int i = 0; i < EIC_EXTINT_NUM; i++) { - active_pulseins[i] = NULL; - last_ms[i] = 0; - last_us[i] = 0; - #ifdef SAMD51 - NVIC_DisableIRQ(EIC_0_IRQn + i); - NVIC_ClearPendingIRQ(EIC_0_IRQn + i); - #endif - } - eic_reset(); - #ifdef SAMD21 - NVIC_DisableIRQ(EIC_IRQn); - NVIC_ClearPendingIRQ(EIC_IRQn); - #endif -} - static void pulsein_set_config(pulseio_pulsein_obj_t* self, bool first_edge) { - uint8_t sense_setting = EIC_CONFIG_FILTEN0; + uint32_t sense_setting; if (!first_edge) { - sense_setting |= EIC_CONFIG_SENSE0_BOTH_Val; + sense_setting = EIC_CONFIG_SENSE0_BOTH_Val; + configure_eic_channel(self->channel, sense_setting); + return; } else if (self->idle_state) { - sense_setting |= EIC_CONFIG_SENSE0_FALL_Val; + sense_setting = EIC_CONFIG_SENSE0_FALL_Val; } else { - sense_setting |= EIC_CONFIG_SENSE0_RISE_Val; + sense_setting = EIC_CONFIG_SENSE0_RISE_Val; } - eic_set_enable(false); - uint8_t config_index = self->channel / 8; - uint8_t position = (self->channel % 8) * 4; - uint32_t masked_value = EIC->CONFIG[config_index].reg & ~(0xf << position); - EIC->CONFIG[config_index].reg = masked_value | (sense_setting << position); - eic_set_enable(true); + turn_on_eic_channel(self->channel, sense_setting, EIC_HANDLER_PULSEIN); } -static void pulsein_interrupt_handler(uint8_t channel) { +void pulsein_interrupt_handler(uint8_t channel) { // Grab the current time first. uint32_t current_us; uint64_t current_ms; @@ -125,16 +63,16 @@ static void pulsein_interrupt_handler(uint8_t channel) { // current_tick gives us the remaining us until the next tick but we want the number since the // last ms. current_us = 1000 - current_us; - pulseio_pulsein_obj_t* self = active_pulseins[channel]; + pulseio_pulsein_obj_t* self = get_eic_channel_data(channel); if (self->first_edge) { self->first_edge = false; pulsein_set_config(self, false); } else { - uint32_t ms_diff = current_ms - last_ms[self->channel]; - uint16_t us_diff = current_us - last_us[self->channel]; + uint32_t ms_diff = current_ms - self->last_ms; + uint16_t us_diff = current_us - self->last_us; uint32_t total_diff = us_diff; - if (last_us[self->channel] > current_us) { - total_diff = 1000 + current_us - last_us[self->channel]; + if (self->last_us > current_us) { + total_diff = 1000 + current_us - self->last_us; if (ms_diff > 1) { total_diff += (ms_diff - 1) * 1000; } @@ -154,8 +92,8 @@ static void pulsein_interrupt_handler(uint8_t channel) { self->start++; } } - last_ms[self->channel] = current_ms; - last_us[self->channel] = current_us; + self->last_ms = current_ms; + self->last_us = current_us; } void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, @@ -163,17 +101,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, if (!pin->has_extint) { mp_raise_RuntimeError("No hardware support on pin"); } - uint32_t mask = 1 << pin->extint_channel; - if (active_pulseins[pin->extint_channel] != NULL || - (eic_get_enable() == 1 && -#ifdef SAMD51 - ((EIC->INTENSET.bit.EXTINT & mask) != 0 || - (EIC->EVCTRL.bit.EXTINTEO & mask) != 0))) { -#endif -#ifdef SAMD21 - ((EIC->INTENSET.vec.EXTINT & mask) != 0 || - (EIC->EVCTRL.vec.EXTINTEO & mask) != 0))) { -#endif + if (eic_get_enable() && !eic_channel_free(pin->extint_channel)) { mp_raise_RuntimeError("EXTINT channel already in use"); } @@ -188,42 +116,22 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, self->start = 0; self->len = 0; self->first_edge = true; + self->last_us = 0; + self->last_ms = 0; - active_pulseins[pin->extint_channel] = self; + set_eic_channel_data(pin->extint_channel, (void*) self); // Check to see if the EIC is enabled and start it up if its not.' - // SAMD51 EIC can only be clocked up to 100mhz so we use the 48mhz clock. if (eic_get_enable() == 0) { - #ifdef SAMD51 - MCLK->APBAMASK.bit.EIC_ = true; - hri_gclk_write_PCHCTRL_reg(GCLK, EIC_GCLK_ID, - GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos)); - #endif - - #ifdef SAMD21 - PM->APBAMASK.bit.EIC_ = true; - _gclk_enable_channel(EIC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); - #endif - - - #ifdef SAMD21 - NVIC_DisableIRQ(EIC_IRQn); - NVIC_ClearPendingIRQ(EIC_IRQn); - NVIC_EnableIRQ(EIC_IRQn); - #endif + turn_on_external_interrupt_controller(); } gpio_set_pin_function(pin->pin, GPIO_PIN_FUNCTION_A); - #ifdef SAMD51 - NVIC_DisableIRQ(EIC_0_IRQn + self->channel); - NVIC_ClearPendingIRQ(EIC_0_IRQn + self->channel); - NVIC_EnableIRQ(EIC_0_IRQn + self->channel); - #endif + turn_on_cpu_interrupt(self->channel); // Set config will enable the EIC. pulsein_set_config(self, true); - EIC->INTENSET.reg = mask << EIC_INTENSET_EXTINT_Pos; } bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t* self) { @@ -234,39 +142,9 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) { if (common_hal_pulseio_pulsein_deinited(self)) { return; } - uint32_t mask = 1 << self->channel; - EIC->INTENCLR.reg = mask << EIC_INTENSET_EXTINT_Pos; - #ifdef SAMD51 - NVIC_DisableIRQ(EIC_0_IRQn + self->channel); - NVIC_ClearPendingIRQ(EIC_0_IRQn + self->channel); - #endif - active_pulseins[self->channel] = NULL; + turn_off_eic_channel(self->channel); reset_pin(self->pin); self->pin = NO_PIN; - - bool all_null = true; - for (uint8_t i = 0; all_null && i < 16; i++) { - all_null = all_null && active_pulseins[i] == NULL; - } - #ifdef SAMD21 - if (all_null && EIC->INTENSET.reg == 0) { - NVIC_DisableIRQ(EIC_IRQn); - NVIC_ClearPendingIRQ(EIC_IRQn); - } - #endif - // Test if all channels are null and deinit everything if they are. - if (all_null && EIC->EVCTRL.reg == 0 && EIC->INTENSET.reg == 0) { - eic_set_enable(false); - #ifdef SAMD51 - MCLK->APBAMASK.bit.EIC_ = false; - hri_gclk_write_PCHCTRL_reg(GCLK, EIC_GCLK_ID, 0); - #endif - - #ifdef SAMD21 - PM->APBAMASK.bit.EIC_ = false; - hri_gclk_write_CLKCTRL_reg(GCLK, GCLK_CLKCTRL_ID(EIC_GCLK_ID)); - #endif - } } void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) { @@ -289,9 +167,9 @@ void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self, } // Reconfigure the pin and make sure its set to detect the first edge. - last_ms[self->channel] = 0; - last_us[self->channel] = 0; self->first_edge = true; + self->last_ms = 0; + self->last_us = 0; gpio_set_pin_function(self->pin, GPIO_PIN_FUNCTION_A); uint32_t mask = 1 << self->channel; // Clear previous interrupt state and re-enable it. @@ -343,69 +221,3 @@ uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, common_hal_mcu_enable_interrupts(); return value; } - -void external_interrupt_handler(uint8_t channel) { - pulsein_interrupt_handler(channel); - EIC->INTFLAG.reg = (1 << channel) << EIC_INTFLAG_EXTINT_Pos; -} - -#ifdef SAMD21 -void EIC_Handler(void) { - for (uint8_t i = 0; i < 16; i++) { - if ((EIC->INTFLAG.vec.EXTINT & (1 << i)) != 0) { - external_interrupt_handler(i); - } - } -} -#endif - -#ifdef SAMD51 -void EIC_0_Handler(void) { - external_interrupt_handler(0); -} -void EIC_1_Handler(void) { - external_interrupt_handler(1); -} -void EIC_2_Handler(void) { - external_interrupt_handler(2); -} -void EIC_3_Handler(void) { - external_interrupt_handler(3); -} -void EIC_4_Handler(void) { - external_interrupt_handler(4); -} -void EIC_5_Handler(void) { - external_interrupt_handler(5); -} -void EIC_6_Handler(void) { - external_interrupt_handler(6); -} -void EIC_7_Handler(void) { - external_interrupt_handler(7); -} -void EIC_8_Handler(void) { - external_interrupt_handler(8); -} -void EIC_9_Handler(void) { - external_interrupt_handler(9); -} -void EIC_10_Handler(void) { - external_interrupt_handler(10); -} -void EIC_11_Handler(void) { - external_interrupt_handler(11); -} -void EIC_12_Handler(void) { - external_interrupt_handler(12); -} -void EIC_13_Handler(void) { - external_interrupt_handler(13); -} -void EIC_14_Handler(void) { - external_interrupt_handler(14); -} -void EIC_15_Handler(void) { - external_interrupt_handler(15); -} -#endif diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.h b/ports/atmel-samd/common-hal/pulseio/PulseIn.h index e3af42e0a3..3d79b50c3c 100644 --- a/ports/atmel-samd/common-hal/pulseio/PulseIn.h +++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.h @@ -41,8 +41,12 @@ typedef struct { volatile uint16_t start; volatile uint16_t len; volatile bool first_edge; + volatile uint64_t last_ms; + volatile uint16_t last_us; } pulseio_pulsein_obj_t; void pulsein_reset(void); +void pulsein_interrupt_handler(uint8_t channel); + #endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PULSEIO_PULSEIN_H diff --git a/ports/atmel-samd/common-hal/pulseio/PulseOut.c b/ports/atmel-samd/common-hal/pulseio/PulseOut.c index 95b0bbee07..8e715d4109 100644 --- a/ports/atmel-samd/common-hal/pulseio/PulseOut.c +++ b/ports/atmel-samd/common-hal/pulseio/PulseOut.c @@ -31,11 +31,11 @@ #include "hal/include/hal_gpio.h" #include "mpconfigport.h" +#include "peripherals/pins.h" +#include "peripherals/timers.h" #include "py/gc.h" #include "py/runtime.h" -#include "samd21_pins.h" #include "shared-bindings/pulseio/PulseOut.h" -#include "timers.h" // This timer is shared amongst all PulseOut objects under the assumption that // the code is single threaded. diff --git a/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c new file mode 100644 index 0000000000..ddc5452950 --- /dev/null +++ b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c @@ -0,0 +1,157 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "common-hal/rotaryio/IncrementalEncoder.h" + +#include "atmel_start_pins.h" + +#include "peripherals/external_interrupts.h" +#include "py/runtime.h" + +void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t* self, + const mcu_pin_obj_t* pin_a, const mcu_pin_obj_t* pin_b) { + if (!pin_a->has_extint || !pin_a->has_extint) { + mp_raise_RuntimeError("Both pins must support hardware interrupts"); + } + + // TODO: The SAMD51 has a peripheral dedicated to quadrature encoder debugging. Use it instead + // of the external interrupt. + + if (eic_get_enable()) { + if (!eic_channel_free(pin_a->extint_channel) || !eic_channel_free(pin_b->extint_channel)) { + mp_raise_RuntimeError("A hardware interrupt channel is already in use"); + } + } else { + turn_on_external_interrupt_controller(); + } + + // These default settings apply when the EIC isn't yet enabled. + self->eic_channel_a = pin_a->extint_channel; + self->eic_channel_b = pin_b->extint_channel; + self->pin_a = pin_a->pin; + self->pin_b = pin_b->pin; + + gpio_set_pin_function(self->pin_a, GPIO_PIN_FUNCTION_A); + gpio_set_pin_pull_mode(self->pin_a, GPIO_PULL_UP); + + gpio_set_pin_function(self->pin_b, GPIO_PIN_FUNCTION_A); + gpio_set_pin_pull_mode(self->pin_b, GPIO_PULL_UP); + + set_eic_channel_data(self->eic_channel_a, (void*) self); + set_eic_channel_data(self->eic_channel_b, (void*) self); + + self->position = 0; + self->quarter_count = 0; + + // Top two bits of self->last_state don't matter, because they'll be gone as soon as + // interrupt handler is called. + self->last_state = + ((uint8_t) gpio_get_pin_level(self->pin_a) << 1) | + (uint8_t) gpio_get_pin_level(self->pin_b); + + turn_on_eic_channel(self->eic_channel_a, EIC_CONFIG_SENSE0_BOTH_Val, EIC_HANDLER_INCREMENTAL_ENCODER); + turn_on_eic_channel(self->eic_channel_b, EIC_CONFIG_SENSE0_BOTH_Val, EIC_HANDLER_INCREMENTAL_ENCODER); +} + +bool common_hal_rotaryio_incrementalencoder_deinited(rotaryio_incrementalencoder_obj_t* self) { + return self->pin_a == NO_PIN; +} + +void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_obj_t* self) { + if (common_hal_rotaryio_incrementalencoder_deinited(self)) { + return; + } + turn_off_eic_channel(self->eic_channel_a); + turn_off_eic_channel(self->eic_channel_b); + reset_pin(self->pin_a); + self->pin_a = NO_PIN; + reset_pin(self->pin_b); + self->pin_b = NO_PIN; +} + +mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t* self) { + return self->position; +} + +void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t* self, + mp_int_t new_position) { + self->position = new_position; +} + +void incrementalencoder_interrupt_handler(uint8_t channel) { + rotaryio_incrementalencoder_obj_t* self = get_eic_channel_data(channel); + + // This table also works for detent both at 11 and 00 + // For 11 at detent: + // Turning cw: 11->01->00->10->11 + // Turning ccw: 11->10->00->01->11 + // For 00 at detent: + // Turning cw: 00->10->11->10->00 + // Turning ccw: 00->01->11->10->00 + + // index table by state + #define BAD 7 + static const int8_t transitions[16] = { + 0, // 00 -> 00 no movement + -1, // 00 -> 01 3/4 ccw (11 detent) or 1/4 ccw (00 at detent) + +1, // 00 -> 10 3/4 cw or 1/4 cw + BAD, // 00 -> 11 non-Gray-code transition + +1, // 01 -> 00 2/4 or 4/4 cw + 0, // 01 -> 01 no movement + BAD, // 01 -> 10 non-Gray-code transition + -1, // 01 -> 11 4/4 or 2/4 ccw + -1, // 10 -> 00 2/4 or 4/4 ccw + BAD, // 10 -> 01 non-Gray-code transition + 0, // 10 -> 10 no movement + +1, // 10 -> 11 4/4 or 2/4 cw + BAD, // 11 -> 00 non-Gray-code transition + +1, // 11 -> 01 1/4 or 3/4 cw + -1, // 11 -> 10 1/4 or 3/4 ccw + 0, // 11 -> 11 no movement + }; + + // Shift the old AB bits to the "old" position, and set the new AB bits. + // TODO(tannewt): If we need more speed then read the pin directly. gpio_get_pin_level has + // smarts to compensate for pin direction we don't need. + self->last_state = (self->last_state & 0x3) << 2 | + ((uint8_t) gpio_get_pin_level(self->pin_a) << 1) | + (uint8_t) gpio_get_pin_level(self->pin_b); + + int8_t quarter_incr = transitions[self->last_state]; + if (quarter_incr == BAD) { + // Missed a transition. We don't know which way we're going, so do nothing. + return; + } + + self->quarter_count += quarter_incr; + if (self->quarter_count >= 4) { + self->position += 1; + self->quarter_count = 0; + } else if (self->quarter_count <= -4) { + self->position -= 1; + self->quarter_count = 0; + } +} diff --git a/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.h b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.h new file mode 100644 index 0000000000..e07cc84d5d --- /dev/null +++ b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.h @@ -0,0 +1,48 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ROTARYIO_INCREMENTALENCODER_H +#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ROTARYIO_INCREMENTALENCODER_H + +#include "common-hal/microcontroller/Pin.h" + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + uint8_t pin_a; + uint8_t pin_b; + uint8_t eic_channel_a:4; + uint8_t eic_channel_b:4; + uint8_t last_state:4; // + int8_t quarter_count:4; // count intermediate transitions between detents + mp_int_t position; +} rotaryio_incrementalencoder_obj_t; + + +void incrementalencoder_interrupt_handler(uint8_t channel); + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ROTARYIO_INCREMENTALENCODER_H diff --git a/ports/atmel-samd/common-hal/rotaryio/__init__.c b/ports/atmel-samd/common-hal/rotaryio/__init__.c new file mode 100644 index 0000000000..0aae79c26a --- /dev/null +++ b/ports/atmel-samd/common-hal/rotaryio/__init__.c @@ -0,0 +1 @@ +// No rotaryio module functions. diff --git a/ports/atmel-samd/common-hal/touchio/TouchIn.c b/ports/atmel-samd/common-hal/touchio/TouchIn.c index 6bb96ff00e..e39a091d79 100644 --- a/ports/atmel-samd/common-hal/touchio/TouchIn.c +++ b/ports/atmel-samd/common-hal/touchio/TouchIn.c @@ -33,11 +33,18 @@ #include "py/mphal.h" #include "shared-bindings/touchio/TouchIn.h" -#include "samd21_pins.h" -#include "tick.h" +#ifdef SAMD21 +#include "hpl/pm/hpl_pm_base.h" +#endif +#include "peripherals/clocks.h" +#include "peripherals/pins.h" + +#include "tick.h" #include "adafruit_ptc.h" +bool touch_enabled = false; + static uint16_t get_raw_reading(touchio_touchin_obj_t *self) { adafruit_ptc_start_conversion(PTC, &self->config); @@ -58,13 +65,21 @@ void common_hal_touchio_touchin_construct(touchio_touchin_obj_t* self, } claim_pin(pin); - /* Setup and enable generic clock source for PTC module. */ - struct system_gclk_chan_config gclk_chan_conf; - system_gclk_chan_get_config_defaults(&gclk_chan_conf); - gclk_chan_conf.source_generator = GCLK_GENERATOR_3; - system_gclk_chan_set_config(PTC_GCLK_ID, &gclk_chan_conf); - system_gclk_chan_enable(PTC_GCLK_ID); - system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_PTC); + // Turn on the PTC if its not in use. We won't turn it off until reset. + #ifdef SAMD21 + if ((( Ptc *) PTC)->CTRLA.bit.ENABLE == 0) { + // We run the PTC at 8mhz so divide the 48mhz clock by 6. + uint8_t gclk = find_free_gclk(6); + if (gclk > GCLK_GEN_NUM) { + mp_raise_RuntimeError("No free GCLKs"); + } + enable_clock_generator(gclk, CLOCK_48MHZ, 6); + + /* Setup and enable generic clock source for PTC module. */ + connect_gclk_to_peripheral(gclk, PTC_GCLK_ID); + + _pm_enable_bus_clock(PM_BUS_APBC, PTC); + } adafruit_ptc_get_config_default(&self->config); self->config.pin = pin->pin; @@ -80,6 +95,7 @@ void common_hal_touchio_touchin_construct(touchio_touchin_obj_t* self, // but for touches using fruit or other objects, the difference is much less. self->threshold = get_raw_reading(self) + 100; + #endif } bool common_hal_touchio_touchin_deinited(touchio_touchin_obj_t* self) { @@ -91,12 +107,21 @@ void common_hal_touchio_touchin_deinit(touchio_touchin_obj_t* self) { if (common_hal_touchio_touchin_deinited(self)) { return; } + // We leave the clocks running because they may be in use by others. + reset_pin(self->config.pin); self->config.pin = NO_PIN; } void touchin_reset() { - // TODO(tannewt): Reset the PTC. + Ptc* ptc = ((Ptc *) PTC); + if (ptc->CTRLA.bit.ENABLE == 1) { + ptc->CTRLA.bit.ENABLE = 0; + while (ptc->CTRLA.bit.ENABLE == 1) {} + + ptc->CTRLA.bit.SWRESET = 1; + while (ptc->CTRLA.bit.SWRESET == 1) {} + } } bool common_hal_touchio_touchin_get_value(touchio_touchin_obj_t *self) { diff --git a/ports/atmel-samd/external_flash/external_flash.c b/ports/atmel-samd/external_flash/external_flash.c index ccc47e5b14..e6c407e73e 100644 --- a/ports/atmel-samd/external_flash/external_flash.c +++ b/ports/atmel-samd/external_flash/external_flash.c @@ -36,12 +36,9 @@ #include "py/obj.h" #include "py/runtime.h" #include "lib/oofatfs/ff.h" -#include "peripherals.h" #include "shared-bindings/microcontroller/__init__.h" #include "supervisor/shared/rgb_led_status.h" -//#include "shared_dma.h" - #include "hal_gpio.h" #include "hal_spi_m_sync.h" diff --git a/ports/atmel-samd/external_flash/qspi_flash.c b/ports/atmel-samd/external_flash/qspi_flash.c index 3fc9d31be4..ec91c21e2d 100644 --- a/ports/atmel-samd/external_flash/qspi_flash.c +++ b/ports/atmel-samd/external_flash/qspi_flash.c @@ -32,8 +32,8 @@ #include "mpconfigboard.h" // for EXTERNAL_FLASH_QSPI_DUAL #include "external_flash/common_commands.h" -#include "peripherals.h" -#include "shared_dma.h" +#include "peripherals/cache.h" +#include "peripherals/dma.h" #include "atmel_start_pins.h" #include "hal_gpio.h" diff --git a/ports/atmel-samd/external_flash/spi_flash.c b/ports/atmel-samd/external_flash/spi_flash.c index 8a8cbaef81..faad8d9e0f 100644 --- a/ports/atmel-samd/external_flash/spi_flash.c +++ b/ports/atmel-samd/external_flash/spi_flash.c @@ -29,8 +29,8 @@ #include #include "external_flash/common_commands.h" -#include "peripherals.h" -#include "shared_dma.h" +#include "peripherals/sercom.h" +#include "py/mpconfig.h" #include "hal_gpio.h" #include "hal_spi_m_sync.h" diff --git a/ports/atmel-samd/freetouch b/ports/atmel-samd/freetouch index c3deba11eb..b6859a349e 160000 --- a/ports/atmel-samd/freetouch +++ b/ports/atmel-samd/freetouch @@ -1 +1 @@ -Subproject commit c3deba11eb4be397ec719cfbfba1abcaecda2c08 +Subproject commit b6859a349efb79e2008d6f6a34e406e93a8e19c0 diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index e6c3a201fe..276ffafe38 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -140,19 +140,27 @@ typedef long mp_off_t; #define CIRCUITPY_MCU_FAMILY samd21 #define MICROPY_PY_SYS_PLATFORM "Atmel SAMD21" #define PORT_HEAP_SIZE (16384 + 4096) -// If you change MICROPY_LONGINT_IMPL, also change MPY_TOOL_LONGINT_IMPL in mpconfigport.mk. -#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) #endif #ifdef SAMD51 #define CIRCUITPY_MCU_FAMILY samd51 #define MICROPY_PY_SYS_PLATFORM "MicroChip SAMD51" #define PORT_HEAP_SIZE (0x20000) // 128KiB -// If you change MICROPY_LONGINT_IMPL, also change MPY_TOOL_LONGINT_IMPL in mpconfigport.mk. -#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +#endif + +#ifdef LONGINT_IMPL_NONE +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) +#endif + +#ifdef LONGINT_IMPL_MPZ +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MP_SSIZE_MAX (0x7fffffff) #endif +#ifdef LONGINT_IMPL_LONGLONG +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG) +#endif + // extra built in modules to add to the list of known ones extern const struct _mp_obj_module_t microcontroller_module; extern const struct _mp_obj_module_t bitbangio_module; @@ -166,6 +174,7 @@ extern const struct _mp_obj_module_t board_module; extern const struct _mp_obj_module_t math_module; extern const struct _mp_obj_module_t os_module; extern const struct _mp_obj_module_t random_module; +extern const struct _mp_obj_module_t rotaryio_module; extern const struct _mp_obj_module_t rtc_module; extern const struct _mp_obj_module_t samd_module; extern const struct _mp_obj_module_t storage_module; @@ -188,9 +197,13 @@ extern const struct _mp_obj_module_t usb_hid_module; #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) #define MICROPY_PY_BUILTINS_REVERSED (1) + #define MICROPY_PY_UERRNO (1) + #define MICROPY_PY_UERRNO_ERRORCODE (0) #define MICROPY_PY_URE (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) - #define MICROPY_PY_FRAMEBUF (1) + #ifndef MICROPY_PY_FRAMEBUF + #define MICROPY_PY_FRAMEBUF (1) + #endif #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) @@ -203,18 +216,23 @@ extern const struct _mp_obj_module_t usb_hid_module; #define AUDIOBUSIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_audiobusio), (mp_obj_t)&audiobusio_module }, #endif + #ifndef EXTRA_BUILTIN_MODULES #define EXTRA_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_audioio), (mp_obj_t)&audioio_module }, \ AUDIOBUSIO_MODULE \ { MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_rotaryio), (mp_obj_t)&rotaryio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module } + #endif #define EXPRESS_BOARD #else #define MICROPY_PY_BUILTINS_REVERSED (0) #define MICROPY_PY_MICROPYTHON_MEM_INFO (0) #define MICROPY_PY_FRAMEBUF (0) + #ifndef EXTRA_BUILTIN_MODULES #define EXTRA_BUILTIN_MODULES + #endif #define MICROPY_PY_BUILTINS_COMPLEX (0) @@ -222,10 +240,32 @@ extern const struct _mp_obj_module_t usb_hid_module; #endif // Disabled for now. -// { MP_OBJ_NEW_QSTR(MP_QSTR_touchio), (mp_obj_t)&touchio_module }, // { MP_OBJ_NEW_QSTR(MP_QSTR__stage), (mp_obj_t)&stage_module }, +#ifdef SAMD21 +#define TOUCHIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_touchio), (mp_obj_t)&touchio_module }, +#endif +#ifdef SAMD51 +#define TOUCHIO_MODULE +#endif +// A pIRKey has minimal I/O needs. Remove unneeded modules to make room +// for frozen modules. math is very large and is also removed. +#ifdef PIRKEY_M0 +#define MICROPY_PORT_BUILTIN_MODULES \ + { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_busio), (mp_obj_t)&busio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_digitalio), (mp_obj_t)&digitalio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_microcontroller), (mp_obj_t)µcontroller_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&os_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_storage), (mp_obj_t)&storage_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&struct_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_supervisor), (mp_obj_t)&supervisor_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid),(mp_obj_t)&usb_hid_module }, +#else #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_analogio), (mp_obj_t)&analogio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \ @@ -244,12 +284,26 @@ extern const struct _mp_obj_module_t usb_hid_module; { MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&math_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid),(mp_obj_t)&usb_hid_module }, \ + TOUCHIO_MODULE \ EXTRA_BUILTIN_MODULES +#endif #define MICROPY_PORT_BUILTIN_DEBUG_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_uheap),(mp_obj_t)&uheap_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_ustack),(mp_obj_t)&ustack_module } +#define MICROPY_PY_UERRNO_LIST \ + X(EPERM) \ + X(ENOENT) \ + X(EIO) \ + X(EAGAIN) \ + X(ENOMEM) \ + X(EACCES) \ + X(EEXIST) \ + X(ENODEV) \ + X(EISDIR) \ + X(EINVAL) \ + // We need to provide a declaration/definition of alloca() #include @@ -264,7 +318,7 @@ extern const struct _mp_obj_module_t usb_hid_module; #define MP_STATE_PORT MP_STATE_VM -#include "shared_dma.h" +#include "peripherals/dma.h" #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; \ @@ -272,6 +326,7 @@ extern const struct _mp_obj_module_t usb_hid_module; mp_obj_t playing_audio[AUDIO_DMA_CHANNEL_COUNT]; \ mp_obj_t rtc_time_source; \ FLASH_ROOT_POINTERS \ + mp_obj_t gamepad_singleton; \ void run_background_tasks(void); #define MICROPY_VM_HOOK_LOOP run_background_tasks(); diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk index 0f3f399e22..c2eedfdc31 100644 --- a/ports/atmel-samd/mpconfigport.mk +++ b/ports/atmel-samd/mpconfigport.mk @@ -1,12 +1,18 @@ # Define an equivalent for MICROPY_LONGINT_IMPL, to pass to $(MPY-TOOL) in py/mkrules.mk # $(MPY-TOOL) needs to know what kind of longint to use (if any) to freeze long integers. # This should correspond to the MICROPY_LONGINT_IMPL definition in mpconfigport.h. -ifeq ($(CHIP_FAMILY), samd21) + +ifeq ($(LONGINT_IMPL),NONE) MPY_TOOL_LONGINT_IMPL = -mlongint-impl=none endif -ifeq ($(CHIP_FAMILY), samd51) +ifeq ($(LONGINT_IMPL),MPZ) MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz endif +ifeq ($(LONGINT_IMPL),LONGLONG) +MPY_TOOL_LONGINT_IMPL = -mlongint-impl=longlong +endif + + INTERNAL_LIBM = 1 diff --git a/ports/atmel-samd/mphalport.c b/ports/atmel-samd/mphalport.c index cdf27fe028..c1b8ce5504 100644 --- a/ports/atmel-samd/mphalport.c +++ b/ports/atmel-samd/mphalport.c @@ -28,7 +28,7 @@ int mp_hal_stdin_rx_chr(void) { #ifdef MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_LOOP #endif - // if (reload_next_character) { + // if (reload_requested) { // return CHAR_CTRL_D; // } if (usb_bytes_available()) { diff --git a/ports/atmel-samd/samd21_peripherals.h b/ports/atmel-samd/peripherals/adc.h similarity index 78% rename from ports/atmel-samd/samd21_peripherals.h rename to ports/atmel-samd/peripherals/adc.h index 805717695a..6530b1dcdc 100644 --- a/ports/atmel-samd/samd21_peripherals.h +++ b/ports/atmel-samd/peripherals/adc.h @@ -24,15 +24,12 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H -#define MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_ADC_H +#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_ADC_H #include "include/sam.h" #include "hal/include/hal_adc_sync.h" -void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index); -uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad); -bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad); void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance); -#endif // MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H +#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_ADC_H diff --git a/ports/atmel-samd/samd51_peripherals.h b/ports/atmel-samd/peripherals/cache.h similarity index 81% rename from ports/atmel-samd/samd51_peripherals.h rename to ports/atmel-samd/peripherals/cache.h index 6643379a5c..b260568a3b 100644 --- a/ports/atmel-samd/samd51_peripherals.h +++ b/ports/atmel-samd/peripherals/cache.h @@ -27,14 +27,6 @@ #ifndef MICROPY_INCLUDED_ATMEL_SAMD_SAMD51_PERIPHERALS_H #define MICROPY_INCLUDED_ATMEL_SAMD_SAMD51_PERIPHERALS_H -#include "sam.h" -#include "hal/include/hal_adc_sync.h" - -void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index); -uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad); -bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad); -void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance); - void samd_peripherals_disable_and_clear_cache(void); void samd_peripherals_enable_cache(void); diff --git a/ports/atmel-samd/clocks.c b/ports/atmel-samd/peripherals/clocks.c similarity index 70% rename from ports/atmel-samd/clocks.c rename to ports/atmel-samd/peripherals/clocks.c index a890210bf4..bfcca45475 100644 --- a/ports/atmel-samd/clocks.c +++ b/ports/atmel-samd/peripherals/clocks.c @@ -56,41 +56,20 @@ uint8_t find_free_gclk(uint16_t divisor) { return 0xff; } -void reset_gclks(void) { - // Never reset GCLK0 because its used for the core - #if CONF_GCLK_GEN_1_GENEN == 0 - disable_gclk(1); - #endif - #if CONF_GCLK_GEN_2_GENEN == 0 - disable_gclk(2); - #endif - #if CONF_GCLK_GEN_3_GENEN == 0 - disable_gclk(3); - #endif - #if CONF_GCLK_GEN_4_GENEN == 0 - disable_gclk(4); - #endif - #if CONF_GCLK_GEN_5_GENEN == 0 - disable_gclk(5); - #endif - #if CONF_GCLK_GEN_6_GENEN == 0 - disable_gclk(6); - #endif - #if CONF_GCLK_GEN_7_GENEN == 0 - disable_gclk(7); - #endif - #ifdef SAMD51 - #if CONF_GCLK_GEN_8_GENEN == 0 - disable_gclk(8); - #endif - #if CONF_GCLK_GEN_9_GENEN == 0 - disable_gclk(9); - #endif - #if CONF_GCLK_GEN_10_GENEN == 0 - disable_gclk(10); - #endif - #if CONF_GCLK_GEN_11_GENEN == 0 - disable_gclk(11); - #endif - #endif +static uint8_t last_static_clock = 0; + +void init_dynamic_clocks(void) { + // Find the last statically initialized clock and save it. Everything after will be reset with + // the VM via reset_gclks. + for (uint8_t i = 0; i < GCLK_GEN_NUM; i++) { + if (gclk_enabled(i)) { + last_static_clock = i; + } + } +} + +void reset_gclks(void) { + for (uint8_t i = last_static_clock + 1; i < GCLK_GEN_NUM; i++) { + disable_gclk(i); + } } diff --git a/ports/atmel-samd/clocks.h b/ports/atmel-samd/peripherals/clocks.h similarity index 97% rename from ports/atmel-samd/clocks.h rename to ports/atmel-samd/peripherals/clocks.h index 6b7cfedce0..22c166d3e2 100644 --- a/ports/atmel-samd/clocks.h +++ b/ports/atmel-samd/peripherals/clocks.h @@ -63,11 +63,13 @@ static inline bool board_has_crystal(void) { } void clock_init(void); +void init_dynamic_clocks(void); bool clock_get_enabled(uint8_t type, uint8_t index); bool clock_get_parent(uint8_t type, uint8_t index, uint8_t *p_type, uint8_t *p_index); uint32_t clock_get_frequency(uint8_t type, uint8_t index); uint32_t clock_get_calibration(uint8_t type, uint8_t index); int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val); +void save_usb_clock_calibration(void); #endif // MICROPY_INCLUDED_ATMEL_SAMD_CLOCKS_H diff --git a/ports/atmel-samd/shared_dma.c b/ports/atmel-samd/peripherals/dma.c similarity index 62% rename from ports/atmel-samd/shared_dma.c rename to ports/atmel-samd/peripherals/dma.c index edc2d0f1a0..664c6aea8f 100644 --- a/ports/atmel-samd/shared_dma.c +++ b/ports/atmel-samd/peripherals/dma.c @@ -23,7 +23,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "shared_dma.h" +#include "peripherals/dma.h" #include @@ -48,164 +48,6 @@ COMPILER_ALIGNED(16) static DmacDescriptor write_back_descriptors[DMA_CHANNEL_CO #define FIRST_SERCOM_TX_TRIGSRC 0x05 #endif -static uint8_t sercom_index(Sercom* sercom) { - #ifdef SAMD21 - return ((uint32_t) sercom - (uint32_t) SERCOM0) / 0x400; - #else - const Sercom* sercoms[SERCOM_INST_NUM] = SERCOM_INSTS; - for (uint8_t i = 0; i < SERCOM_INST_NUM; i++) { - if (sercoms[i] == sercom) { - return i; - } - } - return 0; - #endif -} - -void dma_configure(uint8_t channel_number, uint8_t trigsrc, bool output_event) { - #ifdef SAMD21 - common_hal_mcu_disable_interrupts(); - /** Select the DMA channel and clear software trigger */ - DMAC->CHID.reg = DMAC_CHID_ID(channel_number); - DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; - DMAC->CHCTRLA.reg = DMAC_CHCTRLA_SWRST; - DMAC->SWTRIGCTRL.reg &= (uint32_t)(~(1 << channel_number)); - uint32_t event_output_enable = 0; - if (output_event) { - event_output_enable = DMAC_CHCTRLB_EVOE; - } - DMAC->CHCTRLB.reg = DMAC_CHCTRLB_LVL_LVL0 | - DMAC_CHCTRLB_TRIGSRC(trigsrc) | - DMAC_CHCTRLB_TRIGACT_BEAT | - event_output_enable; - common_hal_mcu_enable_interrupts(); - #endif - - #ifdef SAMD51 - DmacChannel* channel = &DMAC->Channel[channel_number]; - channel->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; - channel->CHCTRLA.reg = DMAC_CHCTRLA_SWRST; - if (output_event) { - channel->CHEVCTRL.reg = DMAC_CHEVCTRL_EVOE; - } - channel->CHCTRLA.reg = DMAC_CHCTRLA_TRIGSRC(trigsrc) | - DMAC_CHCTRLA_TRIGACT_BURST | - DMAC_CHCTRLA_BURSTLEN_SINGLE; - #endif -} - -void dma_enable_channel(uint8_t channel_number) { - #ifdef SAMD21 - common_hal_mcu_disable_interrupts(); - /** Select the DMA channel and clear software trigger */ - DMAC->CHID.reg = DMAC_CHID_ID(channel_number); - // Clear any previous interrupts. - DMAC->CHINTFLAG.reg = DMAC_CHINTFLAG_MASK; - DMAC->CHCTRLA.bit.ENABLE = true; - common_hal_mcu_enable_interrupts(); - #endif - - #ifdef SAMD51 - DmacChannel* channel = &DMAC->Channel[channel_number]; - channel->CHCTRLA.bit.ENABLE = true; - // Clear any previous interrupts. - channel->CHINTFLAG.reg = DMAC_CHINTFLAG_MASK; - #endif -} - -void dma_disable_channel(uint8_t channel_number) { - #ifdef SAMD21 - common_hal_mcu_disable_interrupts(); - /** Select the DMA channel and clear software trigger */ - DMAC->CHID.reg = DMAC_CHID_ID(channel_number); - DMAC->CHCTRLA.bit.ENABLE = false; - common_hal_mcu_enable_interrupts(); - #endif - - #ifdef SAMD51 - DmacChannel* channel = &DMAC->Channel[channel_number]; - channel->CHCTRLA.bit.ENABLE = false; - #endif -} - -void dma_suspend_channel(uint8_t channel_number) { - #ifdef SAMD21 - common_hal_mcu_disable_interrupts(); - /** Select the DMA channel and clear software trigger */ - DMAC->CHID.reg = DMAC_CHID_ID(channel_number); - DMAC->CHCTRLB.bit.CMD = DMAC_CHCTRLB_CMD_SUSPEND_Val; - common_hal_mcu_enable_interrupts(); - #endif - - #ifdef SAMD51 - DmacChannel* channel = &DMAC->Channel[channel_number]; - channel->CHCTRLB.reg = DMAC_CHCTRLB_CMD_SUSPEND; - #endif -} - -void dma_resume_channel(uint8_t channel_number) { - #ifdef SAMD21 - common_hal_mcu_disable_interrupts(); - /** Select the DMA channel and clear software trigger */ - DMAC->CHID.reg = DMAC_CHID_ID(channel_number); - DMAC->CHCTRLB.bit.CMD = DMAC_CHCTRLB_CMD_RESUME_Val; - DMAC->CHINTFLAG.reg = DMAC_CHINTFLAG_SUSP; - common_hal_mcu_enable_interrupts(); - #endif - - #ifdef SAMD51 - DmacChannel* channel = &DMAC->Channel[channel_number]; - channel->CHCTRLB.reg = DMAC_CHCTRLB_CMD_RESUME; - #endif -} - -bool dma_channel_enabled(uint8_t channel_number) { - #ifdef SAMD21 - common_hal_mcu_disable_interrupts(); - /** Select the DMA channel and clear software trigger */ - DMAC->CHID.reg = DMAC_CHID_ID(channel_number); - bool enabled = DMAC->CHCTRLA.bit.ENABLE; - common_hal_mcu_enable_interrupts(); - return enabled; - #endif - - #ifdef SAMD51 - DmacChannel* channel = &DMAC->Channel[channel_number]; - return channel->CHCTRLA.bit.ENABLE; - #endif -} - -uint8_t dma_transfer_status(uint8_t channel_number) { - #ifdef SAMD21 - common_hal_mcu_disable_interrupts(); - /** Select the DMA channel and clear software trigger */ - DMAC->CHID.reg = DMAC_CHID_ID(channel_number); - uint8_t status = DMAC->CHINTFLAG.reg; - common_hal_mcu_enable_interrupts(); - return status; - #endif - - #ifdef SAMD51 - DmacChannel* channel = &DMAC->Channel[channel_number]; - return channel->CHINTFLAG.reg; - #endif -} - -static bool channel_free(uint8_t channel_number) { - #ifdef SAMD21 - common_hal_mcu_disable_interrupts(); - DMAC->CHID.reg = DMAC_CHID_ID(channel_number); - bool channel_free = DMAC->CHSTATUS.reg == 0; - common_hal_mcu_enable_interrupts(); - return channel_free; - #endif - - #ifdef SAMD51 - DmacChannel* channel = &DMAC->Channel[channel_number]; - return channel->CHSTATUS.reg == 0; - #endif -} - void init_shared_dma(void) { // Turn on the clocks #ifdef SAMD51 @@ -237,8 +79,8 @@ static int32_t shared_dma_transfer(void* peripheral, const uint8_t* buffer_out, volatile uint32_t* dest, volatile uint32_t* src, uint8_t* buffer_in, uint32_t length, uint8_t tx) { - if (!channel_free(SHARED_TX_CHANNEL) || - (buffer_in != NULL && !channel_free(SHARED_RX_CHANNEL))) { + if (!dma_channel_free(SHARED_TX_CHANNEL) || + (buffer_in != NULL && !dma_channel_free(SHARED_RX_CHANNEL))) { return -1; } diff --git a/ports/atmel-samd/shared_dma.h b/ports/atmel-samd/peripherals/dma.h similarity index 91% rename from ports/atmel-samd/shared_dma.h rename to ports/atmel-samd/peripherals/dma.h index 03e5b276c8..cf256b962c 100644 --- a/ports/atmel-samd/shared_dma.h +++ b/ports/atmel-samd/peripherals/dma.h @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_SHARED_DMA_H -#define MICROPY_INCLUDED_ATMEL_SAMD_SHARED_DMA_H +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_DMA_H +#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_DMA_H #include #include @@ -49,6 +49,8 @@ int32_t qspi_dma_write(uint32_t address, const uint8_t* buffer, uint32_t length) int32_t qspi_dma_read(uint32_t address, uint8_t* buffer, uint32_t length); #endif +uint8_t sercom_index(Sercom* sercom); + int32_t sercom_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_t length); int32_t sercom_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_t tx); int32_t sercom_dma_transfer(Sercom* sercom, const uint8_t* buffer_out, uint8_t* buffer_in, uint32_t length); @@ -58,8 +60,9 @@ void dma_enable_channel(uint8_t channel_number); void dma_disable_channel(uint8_t channel_number); void dma_suspend_channel(uint8_t channel_number); void dma_resume_channel(uint8_t channel_number); +bool dma_channel_free(uint8_t channel_number); bool dma_channel_enabled(uint8_t channel_number); uint8_t dma_transfer_status(uint8_t channel_number); DmacDescriptor* dma_descriptor(uint8_t channel_number); -#endif // MICROPY_INCLUDED_ATMEL_SAMD_SHARED_DMA_H +#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_DMA_H diff --git a/ports/atmel-samd/peripherals/events.c b/ports/atmel-samd/peripherals/events.c new file mode 100644 index 0000000000..2f6aea7166 --- /dev/null +++ b/ports/atmel-samd/peripherals/events.c @@ -0,0 +1,59 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "peripherals/events.h" +#include "py/runtime.h" + +uint8_t find_async_event_channel(void) { + int8_t channel; + for (channel = EVSYS_CHANNELS - 1; channel > 0; channel--) { + if (event_channel_free(channel)) { + break; + } + } + if (channel < 0) { + mp_raise_RuntimeError("All event channels in use"); + } + return channel; +} + +#ifdef SAMD21 +#define EVSYS_SYNCH_NUM EVSYS_CHANNELS +#endif +uint8_t find_sync_event_channel(void) { + uint8_t channel; + for (channel = 0; channel < EVSYS_SYNCH_NUM; channel++) { + if (event_channel_free(channel)) { + break; + } + } + if (channel >= EVSYS_SYNCH_NUM) { + mp_raise_RuntimeError("All sync event channels in use"); + } + return channel; +} diff --git a/ports/atmel-samd/events.h b/ports/atmel-samd/peripherals/events.h similarity index 97% rename from ports/atmel-samd/events.h rename to ports/atmel-samd/peripherals/events.h index 64093c0ab3..0073142f11 100644 --- a/ports/atmel-samd/events.h +++ b/ports/atmel-samd/peripherals/events.h @@ -44,4 +44,6 @@ void init_event_channel_interrupt(uint8_t channel, uint8_t gclk, uint8_t generat bool event_interrupt_active(uint8_t channel); bool event_interrupt_overflow(uint8_t channel); +bool event_channel_free(uint8_t channel); + #endif // MICROPY_INCLUDED_ATMEL_SAMD_EVENTS_H diff --git a/ports/atmel-samd/peripherals/external_interrupts.c b/ports/atmel-samd/peripherals/external_interrupts.c new file mode 100644 index 0000000000..dfec6c9987 --- /dev/null +++ b/ports/atmel-samd/peripherals/external_interrupts.c @@ -0,0 +1,105 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "common-hal/pulseio/PulseIn.h" +#include "common-hal/rotaryio/IncrementalEncoder.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "peripherals/external_interrupts.h" + +#include "sam.h" + +// This structure is used to share per-channel storage amongst all users of external interrupts. +// Without this there would be multiple arrays even though they are disjoint because each channel +// has one user. +static void *channel_data[EIC_EXTINT_NUM]; +static uint8_t channel_handler[EIC_EXTINT_NUM]; + +void external_interrupt_handler(uint8_t channel) { + uint8_t handler = channel_handler[channel]; + if (handler == EIC_HANDLER_PULSEIN) { + pulsein_interrupt_handler(channel); + } else if (handler == EIC_HANDLER_INCREMENTAL_ENCODER) { + incrementalencoder_interrupt_handler(channel); + } + EIC->INTFLAG.reg = (1 << channel) << EIC_INTFLAG_EXTINT_Pos; +} + +void configure_eic_channel(uint8_t eic_channel, uint32_t sense_setting) { + uint8_t config_index = eic_channel / 8; + uint8_t position = (eic_channel % 8) * 4; + #ifdef SAMD51 + eic_set_enable(false); + #endif + common_hal_mcu_disable_interrupts(); + uint32_t masked_value = EIC->CONFIG[config_index].reg & ~(0xf << position); + EIC->CONFIG[config_index].reg = masked_value | (sense_setting << position); + common_hal_mcu_enable_interrupts(); + #ifdef SAMD51 + eic_set_enable(true); + #endif +} + +void turn_on_eic_channel(uint8_t eic_channel, uint32_t sense_setting, + uint8_t channel_interrupt_handler) { + // We do very light filtering using majority voting. + sense_setting |= EIC_CONFIG_FILTEN0; + configure_eic_channel(eic_channel, sense_setting); + uint32_t mask = 1 << eic_channel; + EIC->INTENSET.reg = mask << EIC_INTENSET_EXTINT_Pos; + if (channel_interrupt_handler != EIC_HANDLER_NO_INTERRUPT) { + channel_handler[eic_channel] = channel_interrupt_handler; + turn_on_cpu_interrupt(eic_channel); + } +} + +void turn_off_eic_channel(uint8_t eic_channel) { + uint32_t mask = 1 << eic_channel; + EIC->INTENCLR.reg = mask << EIC_INTENSET_EXTINT_Pos; + #ifdef SAMD51 + NVIC_DisableIRQ(EIC_0_IRQn + eic_channel); + NVIC_ClearPendingIRQ(EIC_0_IRQn + eic_channel); + #endif + channel_data[eic_channel] = NULL; + + #ifdef SAMD21 + if (EIC->INTENSET.reg == 0) { + NVIC_DisableIRQ(EIC_IRQn); + NVIC_ClearPendingIRQ(EIC_IRQn); + } + #endif + // Test if all channels are null and deinit everything if they are. + if (EIC->EVCTRL.reg == 0 && EIC->INTENSET.reg == 0) { + turn_off_external_interrupt_controller(); + } +} + +void* get_eic_channel_data(uint8_t eic_channel) { + return channel_data[eic_channel]; +} + +void set_eic_channel_data(uint8_t eic_channel, void* data) { + channel_data[eic_channel] = data; +} diff --git a/ports/atmel-samd/peripherals/external_interrupts.h b/ports/atmel-samd/peripherals/external_interrupts.h new file mode 100644 index 0000000000..12d8206770 --- /dev/null +++ b/ports/atmel-samd/peripherals/external_interrupts.h @@ -0,0 +1,54 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_EXTERNAL_INTERRUPTS_H +#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_EXTERNAL_INTERRUPTS_H + +#include +#include + +#define EIC_HANDLER_NO_INTERRUPT 0x0 +#define EIC_HANDLER_PULSEIN 0x1 +#define EIC_HANDLER_INCREMENTAL_ENCODER 0x2 + +void turn_on_external_interrupt_controller(void); +void turn_off_external_interrupt_controller(void); +void turn_on_cpu_interrupt(uint8_t eic_channel); +void turn_on_eic_channel(uint8_t eic_channel, uint32_t sense_setting, + uint8_t channel_interrupt_handler); +void configure_eic_channel(uint8_t eic_channel, uint32_t sense_setting); +void turn_off_eic_channel(uint8_t eic_channel); +bool eic_channel_free(uint8_t eic_channel); +bool eic_get_enable(void); +void eic_set_enable(bool value); +void eic_reset(void); + +void* get_eic_channel_data(uint8_t eic_channel); +void set_eic_channel_data(uint8_t eic_channel, void* data); + +void external_interrupt_handler(uint8_t channel); + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_EXTERNAL_INTERRUPTS_H diff --git a/ports/atmel-samd/peripherals/i2s.c b/ports/atmel-samd/peripherals/i2s.c new file mode 100644 index 0000000000..4d99e7b5b9 --- /dev/null +++ b/ports/atmel-samd/peripherals/i2s.c @@ -0,0 +1,46 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "i2s.h" + +#include "clocks.h" + +#include "hpl/gclk/hpl_gclk_base.h" +#ifdef SAMD21 +#include "hpl/pm/hpl_pm_base.h" +#endif + +void i2s_set_enable(bool enable) { + while (I2S->SYNCBUSY.bit.ENABLE == 1) {} + I2S->CTRLA.bit.ENABLE = enable; + while (I2S->SYNCBUSY.bit.ENABLE == 1) {} +} + +void i2s_set_clock_unit_enable(uint8_t clock_unit, bool enable) { + while ((I2S->SYNCBUSY.vec.CKEN & (1 << clock_unit)) != 0) {} + I2S->CTRLA.vec.CKEN = 1 << clock_unit; + while ((I2S->SYNCBUSY.vec.CKEN & (1 << clock_unit)) != 0) {} +} diff --git a/ports/atmel-samd/i2s.h b/ports/atmel-samd/peripherals/i2s.h similarity index 100% rename from ports/atmel-samd/i2s.h rename to ports/atmel-samd/peripherals/i2s.h diff --git a/ports/atmel-samd/peripherals/pins.h b/ports/atmel-samd/peripherals/pins.h new file mode 100644 index 0000000000..1ddbf3329e --- /dev/null +++ b/ports/atmel-samd/peripherals/pins.h @@ -0,0 +1,42 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// DO NOT include this file directly. Use shared-bindings/microcontroller/Pin.h instead to ensure +// that all necessary includes are already included. + +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_PINS_H +#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_PINS_H + +#include "mpconfigport.h" + +#ifdef SAMD21 +#include "peripherals/samd21/pins.h" +#endif +#ifdef SAMD51 +#include "peripherals/samd51/pins.h" +#endif + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_PINS_H diff --git a/ports/atmel-samd/peripherals/samd21/adc.c b/ports/atmel-samd/peripherals/samd21/adc.c new file mode 100644 index 0000000000..3a7f1e8116 --- /dev/null +++ b/ports/atmel-samd/peripherals/samd21/adc.c @@ -0,0 +1,47 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hal/include/hal_adc_sync.h" +#include "hpl/gclk/hpl_gclk_base.h" +#include "hpl/pm/hpl_pm_base.h" + +// Do initialization and calibration setup needed for any use of the ADC. +// The reference and resolution should be set by the caller. +void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance) { + // Turn the clocks on. + _pm_enable_bus_clock(PM_BUS_APBC, ADC); + _gclk_enable_channel(ADC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); + + adc_sync_init(adc, instance, (void *)NULL); + + // Load the factory calibration + hri_adc_write_CALIB_BIAS_CAL_bf(ADC, (*((uint32_t*) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos); + // Bits 7:5 + uint16_t linearity = ((*((uint32_t*) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5; + // Bits 4:0 + linearity |= (*((uint32_t*) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos; + hri_adc_write_CALIB_LINEARITY_CAL_bf(ADC, linearity); +} diff --git a/ports/atmel-samd/pins.h b/ports/atmel-samd/peripherals/samd21/cache.c similarity index 79% rename from ports/atmel-samd/pins.h rename to ports/atmel-samd/peripherals/samd21/cache.c index 1842efbc06..641b5e1155 100644 --- a/ports/atmel-samd/pins.h +++ b/ports/atmel-samd/peripherals/samd21/cache.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2017 Dan Halbert for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,16 +24,9 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PINS_H -#define MICROPY_INCLUDED_ATMEL_SAMD_PINS_H +// The SAMD21 doesn't have a cache so we have nothing to do. +void samd_peripherals_disable_and_clear_cache(void) { +} -#include "mpconfigport.h" - -#ifdef SAMD21 -#include "samd21_pins.h" -#endif -#ifdef SAMD51 -#include "samd51_pins.h" -#endif - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_PINS_H +void samd_peripherals_enable_cache(void) { +} diff --git a/ports/atmel-samd/samd21_clocks.c b/ports/atmel-samd/peripherals/samd21/clocks.c similarity index 77% rename from ports/atmel-samd/samd21_clocks.c rename to ports/atmel-samd/peripherals/samd21/clocks.c index 0fc4d63e50..51b7ad993d 100644 --- a/ports/atmel-samd/samd21_clocks.c +++ b/ports/atmel-samd/peripherals/samd21/clocks.c @@ -24,15 +24,24 @@ * THE SOFTWARE. */ -#include "clocks.h" +#include +#include -#include "hpl_gclk_config.h" +#include "peripherals/clocks.h" + +#include "hal/include/hal_flash.h" #include "bindings/samd/Clock.h" #include "shared-bindings/microcontroller/__init__.h" #include "py/runtime.h" +#ifdef EXPRESS_BOARD +#define INTERNAL_CIRCUITPY_CONFIG_START_ADDR (0x00040000 - NVMCTRL_ROW_SIZE - CIRCUITPY_INTERNAL_NVM_SIZE) +#else +#define INTERNAL_CIRCUITPY_CONFIG_START_ADDR (0x00040000 - 0x010000 - NVMCTRL_ROW_SIZE - CIRCUITPY_INTERNAL_NVM_SIZE) +#endif + bool gclk_enabled(uint8_t gclk) { common_hal_mcu_disable_interrupts(); // Explicitly do a byte write so the peripheral knows we're just wanting to read the channel @@ -102,17 +111,48 @@ static void init_clock_source_xosc32k(void) { while (!SYSCTRL->PCLKSR.bit.XOSC32KRDY) {} } -static void init_clock_source_dfll48m(void) { +static void init_clock_source_dfll48m_xosc(void) { + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE; + while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {} + SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(0x1f / 4) | + SYSCTRL_DFLLMUL_FSTEP(0xff / 4) | + SYSCTRL_DFLLMUL_MUL(48000000 / 32768); + uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) >> FUSES_DFLL48M_COARSE_CAL_Pos; + if (coarse == 0x3f) { + coarse = 0x1f; + } + SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | + SYSCTRL_DFLLVAL_FINE(512); + + SYSCTRL->DFLLCTRL.reg = 0; + while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {} + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_MODE | + SYSCTRL_DFLLCTRL_ENABLE; + while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {} + while (GCLK->STATUS.bit.SYNCBUSY) {} +} + +static void init_clock_source_dfll48m_usb(void) { SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE; while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {} SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(1) | SYSCTRL_DFLLMUL_FSTEP(1) | SYSCTRL_DFLLMUL_MUL(48000); uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) >> FUSES_DFLL48M_COARSE_CAL_Pos; - if (coarse == 0x3f) + if (coarse == 0x3f) { coarse = 0x1f; + } + uint32_t fine = 512; + #ifdef CALIBRATE_CRYSTALLESS + // This is stored in an NVM page after the text and data storage but before + // the optional file system. The first 16 bytes are the identifier for the + // section. + if (strcmp((char*) INTERNAL_CIRCUITPY_CONFIG_START_ADDR, "CIRCUITPYTHON1") == 0) { + fine = ((uint16_t *) INTERNAL_CIRCUITPY_CONFIG_START_ADDR)[8]; + } + #endif SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | - SYSCTRL_DFLLVAL_FINE(512); + SYSCTRL_DFLLVAL_FINE(fine); SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_USBCRM | SYSCTRL_DFLLCTRL_MODE | @@ -124,17 +164,30 @@ static void init_clock_source_dfll48m(void) { void clock_init(void) { init_clock_source_osc8m(); - if (board_has_crystal()) + if (board_has_crystal()) { init_clock_source_xosc32k(); - else + } else { init_clock_source_osc32k(); + } + + if (board_has_crystal()) { + enable_clock_generator(3, GCLK_GENCTRL_SRC_XOSC32K_Val, 1); + connect_gclk_to_peripheral(3, GCLK_CLKCTRL_ID_DFLL48_Val); + init_clock_source_dfll48m_xosc(); + } else { + init_clock_source_dfll48m_usb(); + } + enable_clock_generator(0, GCLK_GENCTRL_SRC_DFLL48M_Val, 1); enable_clock_generator(1, GCLK_GENCTRL_SRC_DFLL48M_Val, 150); - init_clock_source_dfll48m(); - if (board_has_crystal()) + if (board_has_crystal()) { enable_clock_generator(2, GCLK_GENCTRL_SRC_XOSC32K_Val, 32); - else + } else { enable_clock_generator(2, GCLK_GENCTRL_SRC_OSC32K_Val, 32); + } + + // Do this after all static clock init so that they aren't used dynamically. + init_dynamic_clocks(); } static bool clk_enabled(uint8_t clk) { @@ -310,6 +363,41 @@ int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val) { return -2; // calibration is read only } +void save_usb_clock_calibration(void) { + #ifndef CALIBRATE_CRYSTALLESS + return; + #endif + // If we are on USB lets double check our fine calibration for the clock and + // save the new value if its different enough. + SYSCTRL->DFLLSYNC.bit.READREQ = 1; + uint16_t saved_calibration = 0x1ff; + if (strcmp((char*) INTERNAL_CIRCUITPY_CONFIG_START_ADDR, "CIRCUITPYTHON1") == 0) { + saved_calibration = ((uint16_t *) INTERNAL_CIRCUITPY_CONFIG_START_ADDR)[8]; + } + while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { + // TODO(tannewt): Run the mass storage stuff if this takes a while. + } + int16_t current_calibration = SYSCTRL->DFLLVAL.bit.FINE; + if (abs(current_calibration - saved_calibration) > 10) { + // Copy the full internal config page to memory. + uint8_t page_buffer[NVMCTRL_ROW_SIZE]; + memcpy(page_buffer, (uint8_t*) INTERNAL_CIRCUITPY_CONFIG_START_ADDR, NVMCTRL_ROW_SIZE); + + // Modify it. + memcpy(page_buffer, "CIRCUITPYTHON1", 15); + // First 16 bytes (0-15) are ID. Little endian! + page_buffer[16] = current_calibration & 0xff; + page_buffer[17] = current_calibration >> 8; + + // Write it back. + // We don't use features that use any advanced NVMCTRL features so we can fake the descriptor + // whenever we need it instead of storing it long term. + struct flash_descriptor desc; + desc.dev.hw = NVMCTRL; + flash_write(&desc, (uint32_t) INTERNAL_CIRCUITPY_CONFIG_START_ADDR, page_buffer, NVMCTRL_ROW_SIZE); + } +} + #ifdef SAMD21_EXPOSE_ALL_CLOCKS CLOCK_SOURCE(XOSC); CLOCK_SOURCE(GCLKIN); diff --git a/ports/atmel-samd/peripherals/samd21/dma.c b/ports/atmel-samd/peripherals/samd21/dma.c new file mode 100644 index 0000000000..3a399745ac --- /dev/null +++ b/ports/atmel-samd/peripherals/samd21/dma.c @@ -0,0 +1,118 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017-2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "peripherals/dma.h" + +#include + +#include "py/gc.h" +#include "py/mpstate.h" + +#include "hal/utils/include/utils.h" + +#include "shared-bindings/microcontroller/__init__.h" + +uint8_t sercom_index(Sercom* sercom) { + return ((uint32_t) sercom - (uint32_t) SERCOM0) / 0x400; +} + +void dma_configure(uint8_t channel_number, uint8_t trigsrc, bool output_event) { + common_hal_mcu_disable_interrupts(); + /** Select the DMA channel and clear software trigger */ + DMAC->CHID.reg = DMAC_CHID_ID(channel_number); + DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; + DMAC->CHCTRLA.reg = DMAC_CHCTRLA_SWRST; + DMAC->SWTRIGCTRL.reg &= (uint32_t)(~(1 << channel_number)); + uint32_t event_output_enable = 0; + if (output_event) { + event_output_enable = DMAC_CHCTRLB_EVOE; + } + DMAC->CHCTRLB.reg = DMAC_CHCTRLB_LVL_LVL0 | + DMAC_CHCTRLB_TRIGSRC(trigsrc) | + DMAC_CHCTRLB_TRIGACT_BEAT | + event_output_enable; + common_hal_mcu_enable_interrupts(); +} + +void dma_enable_channel(uint8_t channel_number) { + common_hal_mcu_disable_interrupts(); + /** Select the DMA channel and clear software trigger */ + DMAC->CHID.reg = DMAC_CHID_ID(channel_number); + // Clear any previous interrupts. + DMAC->CHINTFLAG.reg = DMAC_CHINTFLAG_MASK; + DMAC->CHCTRLA.bit.ENABLE = true; + common_hal_mcu_enable_interrupts(); +} + +void dma_disable_channel(uint8_t channel_number) { + common_hal_mcu_disable_interrupts(); + /** Select the DMA channel and clear software trigger */ + DMAC->CHID.reg = DMAC_CHID_ID(channel_number); + DMAC->CHCTRLA.bit.ENABLE = false; + common_hal_mcu_enable_interrupts(); +} + +void dma_suspend_channel(uint8_t channel_number) { + common_hal_mcu_disable_interrupts(); + /** Select the DMA channel and clear software trigger */ + DMAC->CHID.reg = DMAC_CHID_ID(channel_number); + DMAC->CHCTRLB.bit.CMD = DMAC_CHCTRLB_CMD_SUSPEND_Val; + common_hal_mcu_enable_interrupts(); +} + +void dma_resume_channel(uint8_t channel_number) { + common_hal_mcu_disable_interrupts(); + /** Select the DMA channel and clear software trigger */ + DMAC->CHID.reg = DMAC_CHID_ID(channel_number); + DMAC->CHCTRLB.bit.CMD = DMAC_CHCTRLB_CMD_RESUME_Val; + DMAC->CHINTFLAG.reg = DMAC_CHINTFLAG_SUSP; + common_hal_mcu_enable_interrupts(); +} + +bool dma_channel_enabled(uint8_t channel_number) { + common_hal_mcu_disable_interrupts(); + /** Select the DMA channel and clear software trigger */ + DMAC->CHID.reg = DMAC_CHID_ID(channel_number); + bool enabled = DMAC->CHCTRLA.bit.ENABLE; + common_hal_mcu_enable_interrupts(); + return enabled; +} + +uint8_t dma_transfer_status(uint8_t channel_number) { + common_hal_mcu_disable_interrupts(); + /** Select the DMA channel and clear software trigger */ + DMAC->CHID.reg = DMAC_CHID_ID(channel_number); + uint8_t status = DMAC->CHINTFLAG.reg; + common_hal_mcu_enable_interrupts(); + return status; +} + +bool dma_channel_free(uint8_t channel_number) { + common_hal_mcu_disable_interrupts(); + DMAC->CHID.reg = DMAC_CHID_ID(channel_number); + bool channel_free = DMAC->CHSTATUS.reg == 0; + common_hal_mcu_enable_interrupts(); + return channel_free; +} diff --git a/ports/atmel-samd/events.c b/ports/atmel-samd/peripherals/samd21/events.c similarity index 57% rename from ports/atmel-samd/events.c rename to ports/atmel-samd/peripherals/samd21/events.c index 05a2ae8a73..08b82c91fc 100644 --- a/ports/atmel-samd/events.c +++ b/ports/atmel-samd/peripherals/samd21/events.c @@ -24,137 +24,58 @@ * THE SOFTWARE. */ -#include "events.h" +#include "peripherals/events.h" -#include "clocks.h" +#include "peripherals/clocks.h" #include "py/runtime.h" -#ifdef SAMD21 #include "hpl/pm/hpl_pm_base.h" -#endif - -#ifdef SAMD51 -#include "hri/hri_mclk_d51.h" -#endif void turn_on_event_system(void) { - #ifdef SAMD51 - hri_mclk_set_APBBMASK_EVSYS_bit(MCLK); - #endif - - #ifdef SAMD21 _pm_enable_bus_clock(PM_BUS_APBC, EVSYS); - #endif } void reset_event_system(void) { - #ifdef SAMD51 - EVSYS->CTRLA.bit.SWRST = true; - hri_mclk_clear_APBBMASK_EVSYS_bit(MCLK); - #endif - - #ifdef SAMD21 EVSYS->CTRL.bit.SWRST = true; _pm_disable_bus_clock(PM_BUS_APBC, EVSYS); - #endif } -static bool channel_free(int8_t channel) { +bool event_channel_free(uint8_t channel) { uint8_t generator; - #ifdef SAMD51 - generator = EVSYS->Channel[channel].CHANNEL.bit.EVGEN; - #endif - #ifdef SAMD21 // Explicitly do a byte write so the peripheral knows we're just wanting to read the channel // rather than write to it. *((uint8_t*) &EVSYS->CHANNEL.reg) = channel; generator = (EVSYS->CHANNEL.reg & EVSYS_CHANNEL_EVGEN_Msk) >> EVSYS_CHANNEL_EVGEN_Pos; - #endif return generator == 0; } -uint8_t find_async_event_channel(void) { - int8_t channel; - for (channel = EVSYS_CHANNELS - 1; channel > 0; channel--) { - if (channel_free(channel)) { - break; - } - } - if (channel < 0) { - mp_raise_RuntimeError("All event channels in use"); - } - return channel; -} - -#ifdef SAMD21 -#define EVSYS_SYNCH_NUM EVSYS_CHANNELS -#endif -uint8_t find_sync_event_channel(void) { - uint8_t channel; - for (channel = 0; channel < EVSYS_SYNCH_NUM; channel++) { - if (channel_free(channel)) { - break; - } - } - if (channel >= EVSYS_SYNCH_NUM) { - mp_raise_RuntimeError("All sync event channels in use"); - } - return channel; -} - void disable_event_channel(uint8_t channel_number) { - #ifdef SAMD51 - EVSYS->Channel[channel_number].CHANNEL.reg = 0; - #endif - #ifdef SAMD21 EVSYS->CHANNEL.reg = EVSYS_CHANNEL_CHANNEL(channel_number); - #endif } void disable_event_user(uint8_t user_number) { - #ifdef SAMD51 - EVSYS->USER[user_number].reg = 0; - #endif - #ifdef SAMD21 EVSYS->USER.reg = EVSYS_USER_USER(user_number); - #endif } void connect_event_user_to_channel(uint8_t user, uint8_t channel) { - #ifdef SAMD51 - EVSYS->USER[user].reg = channel + 1; - #endif - #ifdef SAMD21 EVSYS->USER.reg = EVSYS_USER_USER(user) | EVSYS_USER_CHANNEL(channel + 1); - #endif } void init_async_event_channel(uint8_t channel, uint8_t generator) { - #ifdef SAMD51 - EVSYS->Channel[channel].CHANNEL.reg = EVSYS_CHANNEL_EVGEN(generator) | EVSYS_CHANNEL_PATH_ASYNCHRONOUS; - #endif - #ifdef SAMD21 - EVSYS->CHANNEL.reg = EVSYS_CHANNEL_CHANNEL(channel) | EVSYS_CHANNEL_EVGEN(generator) | EVSYS_CHANNEL_PATH_ASYNCHRONOUS; - #endif + EVSYS->CHANNEL.reg = EVSYS_CHANNEL_CHANNEL(channel) | + EVSYS_CHANNEL_EVGEN(generator) | + EVSYS_CHANNEL_PATH_ASYNCHRONOUS; } void init_event_channel_interrupt(uint8_t channel, uint8_t gclk, uint8_t generator) { connect_gclk_to_peripheral(gclk, EVSYS_GCLK_ID_0 + channel); - #ifdef SAMD51 - EVSYS->Channel[channel].CHANNEL.reg = EVSYS_CHANNEL_EVGEN(generator) | - EVSYS_CHANNEL_PATH_SYNCHRONOUS | - EVSYS_CHANNEL_EDGSEL_RISING_EDGE; - EVSYS->Channel[channel].CHINTFLAG.reg = EVSYS_CHINTFLAG_EVD | EVSYS_CHINTFLAG_OVR; - EVSYS->Channel[channel].CHINTENSET.reg = EVSYS_CHINTENSET_EVD | EVSYS_CHINTENSET_OVR; - #endif - #ifdef SAMD21 EVSYS->CHANNEL.reg = EVSYS_CHANNEL_CHANNEL(channel) | EVSYS_CHANNEL_EVGEN(generator) | EVSYS_CHANNEL_PATH_RESYNCHRONIZED | EVSYS_CHANNEL_EDGSEL_RISING_EDGE; - if (channel > 7) { - uint8_t value = 1 << (channel - 7); + if (channel >= 8) { + uint8_t value = 1 << (channel - 8); EVSYS->INTFLAG.reg = EVSYS_INTFLAG_EVDp8(value) | EVSYS_INTFLAG_OVRp8(value); EVSYS->INTENSET.reg = EVSYS_INTENSET_EVDp8(value) | EVSYS_INTENSET_OVRp8(value); } else { @@ -162,14 +83,12 @@ void init_event_channel_interrupt(uint8_t channel, uint8_t gclk, uint8_t generat EVSYS->INTFLAG.reg = EVSYS_INTFLAG_EVD(value) | EVSYS_INTFLAG_OVR(value); EVSYS->INTENSET.reg = EVSYS_INTENSET_EVD(value) | EVSYS_INTENSET_OVR(value); } - #endif } bool event_interrupt_active(uint8_t channel) { bool active = false; - #ifdef SAMD21 - if (channel > 7) { - uint8_t value = 1 << (channel - 7); + if (channel >= 8) { + uint8_t value = 1 << (channel - 8); active = (EVSYS->INTFLAG.reg & EVSYS_INTFLAG_EVDp8(value)) != 0; // Only clear if we know its active, otherwise there is the possibility it becomes active // after we check but before we clear. @@ -183,31 +102,17 @@ bool event_interrupt_active(uint8_t channel) { EVSYS->INTFLAG.reg = EVSYS_INTFLAG_EVD(value) | EVSYS_INTFLAG_OVR(value); } } - #endif - #ifdef SAMD51 - active = EVSYS->Channel[channel].CHINTFLAG.bit.EVD; - // Only clear if we know its active, otherwise there is the possibility it becomes after we - // check but before we clear. - if (active) { - EVSYS->Channel[channel].CHINTFLAG.reg = EVSYS_CHINTFLAG_EVD | EVSYS_CHINTFLAG_OVR; - } - #endif return active; } bool event_interrupt_overflow(uint8_t channel) { bool overflow = false; - #ifdef SAMD21 - if (channel > 7) { - uint8_t value = 1 << (channel - 7); + if (channel >= 8) { + uint8_t value = 1 << (channel - 8); overflow = (EVSYS->INTFLAG.reg & EVSYS_INTFLAG_OVRp8(value)) != 0; } else { uint8_t value = 1 << channel; overflow = (EVSYS->INTFLAG.reg & EVSYS_INTFLAG_OVR(value)) != 0; } - #endif - #ifdef SAMD51 - overflow = EVSYS->Channel[channel].CHINTFLAG.bit.OVR; - #endif return overflow; } diff --git a/ports/atmel-samd/peripherals/samd21/external_interrupts.c b/ports/atmel-samd/peripherals/samd21/external_interrupts.c new file mode 100644 index 0000000000..209c439c0a --- /dev/null +++ b/ports/atmel-samd/peripherals/samd21/external_interrupts.c @@ -0,0 +1,86 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "peripherals/external_interrupts.h" + +#include "hpl/gclk/hpl_gclk_base.h" +#include "peripherals/clocks.h" +#include "sam.h" + +void turn_on_external_interrupt_controller(void) { + PM->APBAMASK.bit.EIC_ = true; + _gclk_enable_channel(EIC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); + eic_set_enable(true); +} + +void turn_off_external_interrupt_controller(void) { + eic_set_enable(false); + PM->APBAMASK.bit.EIC_ = false; + hri_gclk_write_CLKCTRL_reg(GCLK, GCLK_CLKCTRL_ID(EIC_GCLK_ID)); +} + +void turn_on_cpu_interrupt(uint8_t eic_channel) { + // Ignore the channel since the CPU interrupt line is shared. + (void) eic_channel; + + NVIC_DisableIRQ(EIC_IRQn); + NVIC_ClearPendingIRQ(EIC_IRQn); + NVIC_EnableIRQ(EIC_IRQn); +} + +bool eic_get_enable(void) { + return EIC->CTRL.bit.ENABLE; +} + +void eic_set_enable(bool value) { + EIC->CTRL.bit.ENABLE = value; + while (EIC->STATUS.bit.SYNCBUSY != 0) {} +} + +void eic_reset(void) { + EIC->CTRL.bit.SWRST = true; + while (EIC->STATUS.bit.SYNCBUSY != 0) {} + for (int i = 0; i < EIC_EXTINT_NUM; i++) { + set_eic_channel_data(i, NULL); + } + NVIC_DisableIRQ(EIC_IRQn); + NVIC_ClearPendingIRQ(EIC_IRQn); +} + +bool eic_channel_free(uint8_t eic_channel) { + uint32_t mask = 1 << eic_channel; + return get_eic_channel_data(eic_channel) == NULL && + (EIC->INTENSET.vec.EXTINT & mask) == 0 && + (EIC->EVCTRL.vec.EXTINTEO & mask) == 0; +} + +void EIC_Handler(void) { + for (uint8_t i = 0; i < 16; i++) { + if ((EIC->INTFLAG.vec.EXTINT & (1 << i)) != 0) { + external_interrupt_handler(i); + } + } +} diff --git a/ports/atmel-samd/peripherals/samd21/i2s.c b/ports/atmel-samd/peripherals/samd21/i2s.c new file mode 100644 index 0000000000..7df401601d --- /dev/null +++ b/ports/atmel-samd/peripherals/samd21/i2s.c @@ -0,0 +1,46 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "peripherals/i2s.h" + +#include "peripherals/clocks.h" + +#include "hpl/gclk/hpl_gclk_base.h" +#include "hpl/pm/hpl_pm_base.h" + +void turn_on_i2s(void) { + _pm_enable_bus_clock(PM_BUS_APBC, I2S); +} + +void i2s_set_serializer_enable(uint8_t serializer, bool enable) { + while ((I2S->SYNCBUSY.vec.SEREN & (1 << serializer)) != 0) {} + if (enable) { + I2S->CTRLA.vec.SEREN = 1 << serializer; + } else { + I2S->CTRLA.vec.SEREN &= ~(1 << serializer); + } + while ((I2S->SYNCBUSY.vec.SEREN & (1 << serializer)) != 0) {} +} diff --git a/ports/atmel-samd/samd21_pins.c b/ports/atmel-samd/peripherals/samd21/pins.c similarity index 78% rename from ports/atmel-samd/samd21_pins.c rename to ports/atmel-samd/peripherals/samd21/pins.c index eafc4b5fb6..bbb023a54f 100644 --- a/ports/atmel-samd/samd21_pins.c +++ b/ports/atmel-samd/peripherals/samd21/pins.c @@ -26,8 +26,6 @@ #include "shared-bindings/microcontroller/Pin.h" -#include "samd21_pins.h" - #define SERCOM(sercom_index, p_pad) \ { \ .index = sercom_index, \ @@ -93,21 +91,21 @@ const mcu_pin_obj_t pin_## p_name = { \ // Pins in datasheet order. // NOTE(tannewt): TC wave out 0 is commented out because the first channel is // used to vary the 16 bit timer's frequency. -#ifdef PIN_PA00 +#if defined(PIN_PA00) && !defined(IGNORE_PIN_PA00) PIN(PA00, EXTINT_CHANNEL(0), NO_ADC, NO_TOUCH, NO_SERCOM, SERCOM(1, 0), TCC(2, 0), NO_TIMER); #endif -#ifdef PIN_PA01 +#if defined(PIN_PA01) && !defined(IGNORE_PIN_PA01) PIN(PA01, EXTINT_CHANNEL(1), NO_ADC, NO_TOUCH, NO_SERCOM, SERCOM(1, 1), TCC(2, 1), NO_TIMER); #endif -#ifdef PIN_PA02 +#if defined(PIN_PA02) && !defined(IGNORE_PIN_PA02) // Touch is not allowed on A0 (PA02) on Circuit Playground Express. PIN(PA02, EXTINT_CHANNEL(2), ADC_INPUT(0), #ifdef PA02_NO_TOUCH @@ -120,140 +118,140 @@ PIN(PA02, EXTINT_CHANNEL(2), ADC_INPUT(0), NO_TIMER, NO_TIMER); #endif -#ifdef PIN_PA03 +#if defined(PIN_PA03) && !defined(IGNORE_PIN_PA03) PIN(PA03, EXTINT_CHANNEL(3), ADC_INPUT(1), TOUCH(1), NO_SERCOM, NO_SERCOM, NO_TIMER, NO_TIMER); #endif -#ifdef PIN_PB04 +#if defined(PIN_PB04) && !defined(IGNORE_PIN_PB04) PIN(PB04, EXTINT_CHANNEL(4), ADC_INPUT(12), TOUCH(10), NO_SERCOM, NO_SERCOM, NO_TIMER, NO_TIMER); #endif -#ifdef PIN_PB05 +#if defined(PIN_PB05) && !defined(IGNORE_PIN_PB05) PIN(PB05, EXTINT_CHANNEL(5), ADC_INPUT(13), TOUCH(11), NO_SERCOM, NO_SERCOM, NO_TIMER, NO_TIMER); #endif -#ifdef PIN_PB06 +#if defined(PIN_PB06) && !defined(IGNORE_PIN_PB06) PIN(PB06, EXTINT_CHANNEL(6), ADC_INPUT(14), TOUCH(12), NO_SERCOM, NO_SERCOM, NO_TIMER, NO_TIMER); #endif -#ifdef PIN_PB07 +#if defined(PIN_PB07) && !defined(IGNORE_PIN_PB07) PIN(PB07, EXTINT_CHANNEL(7), ADC_INPUT(15), TOUCH(13), NO_SERCOM, NO_SERCOM, NO_TIMER, NO_TIMER); #endif -#ifdef PIN_PB08 +#if defined(PIN_PB08) && !defined(IGNORE_PIN_PB08) PIN(PB08, EXTINT_CHANNEL(8), ADC_INPUT(2), TOUCH(14), NO_SERCOM, SERCOM(4, 0), TC(4, 0), NO_TIMER); #endif -#ifdef PIN_PB09 +#if defined(PIN_PB09) && !defined(IGNORE_PIN_PB09) PIN(PB09, EXTINT_CHANNEL(9), ADC_INPUT(3), TOUCH(15), NO_SERCOM, SERCOM(4, 1), TC(4, 1), NO_TIMER); #endif -#ifdef PIN_PA04 +#if defined(PIN_PA04) && !defined(IGNORE_PIN_PA04) PIN(PA04, EXTINT_CHANNEL(4), ADC_INPUT(4), TOUCH(2), NO_SERCOM, SERCOM(0, 0), TCC(0, 0), NO_TIMER); #endif -#ifdef PIN_PA05 +#if defined(PIN_PA05) && !defined(IGNORE_PIN_PA05) PIN(PA05, EXTINT_CHANNEL(5), ADC_INPUT(5), TOUCH(3), NO_SERCOM, SERCOM(0, 1), TCC(0, 1), NO_TIMER); #endif -#ifdef PIN_PA06 +#if defined(PIN_PA06) && !defined(IGNORE_PIN_PA06) PIN(PA06, EXTINT_CHANNEL(6), ADC_INPUT(6), TOUCH(4), NO_SERCOM, SERCOM(0, 2), TCC(1, 0), NO_TIMER); #endif -#ifdef PIN_PA07 +#if defined(PIN_PA07) && !defined(IGNORE_PIN_PA07) PIN(PA07, EXTINT_CHANNEL(7), ADC_INPUT(7), TOUCH(5), NO_SERCOM, SERCOM(0, 3), TCC(1, 1), NO_TIMER); #endif -#ifdef PIN_PA08 +#if defined(PIN_PA08) && !defined(IGNORE_PIN_PA08) PIN(PA08, NO_EXTINT, ADC_INPUT(16), NO_TOUCH, SERCOM(0, 0), SERCOM(2, 0), TCC(0, 0), TCC(1, 2)); #endif -#ifdef PIN_PA09 +#if defined(PIN_PA09) && !defined(IGNORE_PIN_PA09) PIN(PA09, EXTINT_CHANNEL(9), ADC_INPUT(17), NO_TOUCH, SERCOM(0, 1), SERCOM(2, 1), TCC(0, 1), TCC(1, 3)); #endif -#ifdef PIN_PA10 +#if defined(PIN_PA10) && !defined(IGNORE_PIN_PA10) PIN(PA10, EXTINT_CHANNEL(10), ADC_INPUT(18), NO_TOUCH, SERCOM(0, 2), SERCOM(2, 2), TCC(1, 0), TCC(0, 2)); #endif -#ifdef PIN_PA11 +#if defined(PIN_PA11) && !defined(IGNORE_PIN_PA11) PIN(PA11, EXTINT_CHANNEL(11), ADC_INPUT(19), NO_TOUCH, SERCOM(0, 3), SERCOM(2, 3), TCC(1, 1), TCC(0, 3)); #endif -#ifdef PIN_PB10 +#if defined(PIN_PB10) && !defined(IGNORE_PIN_PB10) PIN(PB10, EXTINT_CHANNEL(10), NO_ADC, NO_TOUCH, NO_SERCOM, SERCOM(4, 2), TC(5, 0), TCC(0, 4)); #endif -#ifdef PIN_PB11 +#if defined(PIN_PB11) && !defined(IGNORE_PIN_PB11) PIN(PB11, EXTINT_CHANNEL(11), NO_ADC, NO_TOUCH, NO_SERCOM, SERCOM(4, 3), TC(5, 1), TCC(0, 5)); #endif -#ifdef PIN_PB12 +#if defined(PIN_PB12) && !defined(IGNORE_PIN_PB12) PIN(PB12, EXTINT_CHANNEL(12), NO_ADC, NO_TOUCH, SERCOM(4, 0), NO_SERCOM, TC(4, 0), TCC(0, 6)); #endif -#ifdef PIN_PB13 +#if defined(PIN_PB13) && !defined(IGNORE_PIN_PB13) PIN(PB13, EXTINT_CHANNEL(13), NO_ADC, NO_TOUCH, SERCOM(4, 1), NO_SERCOM, TC(4, 1), TCC(0, 7)); #endif -#ifdef PIN_PB14 +#if defined(PIN_PB14) && !defined(IGNORE_PIN_PB14) PIN(PB14, EXTINT_CHANNEL(14), NO_ADC, NO_TOUCH, SERCOM(4, 2), NO_SERCOM, @@ -262,28 +260,28 @@ PIN(PB14, EXTINT_CHANNEL(14), NO_ADC, NO_TOUCH, #endif // Second page. -#ifdef PIN_PB15 +#if defined(PIN_PB15) && !defined(IGNORE_PIN_PB15) PIN(PB15, EXTINT_CHANNEL(15), NO_ADC, NO_TOUCH, SERCOM(4, 3), NO_SERCOM, TC(5, 1), NO_TIMER); #endif -#ifdef PIN_PA12 +#if defined(PIN_PA12) && !defined(IGNORE_PIN_PA12) PIN(PA12, EXTINT_CHANNEL(12), NO_ADC, NO_TOUCH, SERCOM(2, 0), SERCOM(4, 0), TCC(2, 0), TCC(0, 6)); #endif -#ifdef PIN_PA13 +#if defined(PIN_PA13) && !defined(IGNORE_PIN_PA13) PIN(PA13, EXTINT_CHANNEL(13), NO_ADC, NO_TOUCH, SERCOM(2, 1), SERCOM(4, 1), TCC(2, 1), TCC(0, 7)); #endif -#ifdef PIN_PA14 +#if defined(PIN_PA14) && !defined(IGNORE_PIN_PA14) PIN(PA14, EXTINT_CHANNEL(14), NO_ADC, NO_TOUCH, SERCOM(2, 2), #ifdef SERCOM4 @@ -294,7 +292,7 @@ PIN(PA14, EXTINT_CHANNEL(14), NO_ADC, NO_TOUCH, TC(3, 0), TCC(0, 4)); #endif -#ifdef PIN_PA15 +#if defined(PIN_PA15) && !defined(IGNORE_PIN_PA15) PIN(PA15, EXTINT_CHANNEL(15), NO_ADC, NO_TOUCH, SERCOM(2, 3), #ifdef SERCOM4 @@ -305,35 +303,35 @@ PIN(PA15, EXTINT_CHANNEL(15), NO_ADC, NO_TOUCH, TC(3, 1), TCC(0, 5)); #endif -#ifdef PIN_PA16 +#if defined(PIN_PA16) && !defined(IGNORE_PIN_PA16) PIN(PA16, EXTINT_CHANNEL(0), NO_ADC, NO_TOUCH, SERCOM(1, 0), SERCOM(3, 0), TCC(2, 0), TCC(0, 6)); #endif -#ifdef PIN_PA17 +#if defined(PIN_PA17) && !defined(IGNORE_PIN_PA17) PIN(PA17, EXTINT_CHANNEL(1), NO_ADC, NO_TOUCH, SERCOM(1, 1), SERCOM(3, 1), TCC(2, 1), TCC(0, 7)); #endif -#ifdef PIN_PA18 +#if defined(PIN_PA18) && !defined(IGNORE_PIN_PA18) PIN(PA18, EXTINT_CHANNEL(2), NO_ADC, NO_TOUCH, SERCOM(1, 2), SERCOM(3, 2), TC(3, 0), TCC(0, 2)); #endif -#ifdef PIN_PA19 +#if defined(PIN_PA19) && !defined(IGNORE_PIN_PA19) PIN(PA19, EXTINT_CHANNEL(3), NO_ADC, NO_TOUCH, SERCOM(1, 3), SERCOM(3, 3), TC(3, 1), TCC(0, 3)); #endif -#ifdef PIN_PB16 +#if defined(PIN_PB16) && !defined(IGNORE_PIN_PB16) PIN(PB16, EXTINT_CHANNEL(0), NO_ADC, NO_TOUCH, SERCOM(5, 0), NO_SERCOM, @@ -344,7 +342,7 @@ PIN(PB16, EXTINT_CHANNEL(0), NO_ADC, NO_TOUCH, #endif TCC(0, 4)); #endif -#ifdef PIN_PB17 +#if defined(PIN_PB17) && !defined(IGNORE_PIN_PB17) PIN(PB17, EXTINT_CHANNEL(1), NO_ADC, NO_TOUCH, SERCOM(5, 1), NO_SERCOM, @@ -355,7 +353,7 @@ PIN(PB17, EXTINT_CHANNEL(1), NO_ADC, NO_TOUCH, #endif TCC(0, 5)); #endif -#ifdef PIN_PA20 +#if defined(PIN_PA20) && !defined(IGNORE_PIN_PA20) PIN(PA20, EXTINT_CHANNEL(4), NO_ADC, NO_TOUCH, SERCOM(5, 2), SERCOM(3, 2), @@ -366,7 +364,7 @@ PIN(PA20, EXTINT_CHANNEL(4), NO_ADC, NO_TOUCH, #endif TCC(0, 6)); #endif -#ifdef PIN_PA21 +#if defined(PIN_PA21) && !defined(IGNORE_PIN_PA21) PIN(PA21, EXTINT_CHANNEL(5), NO_ADC, NO_TOUCH, SERCOM(5, 3), SERCOM(3, 3), @@ -377,7 +375,7 @@ PIN(PA21, EXTINT_CHANNEL(5), NO_ADC, NO_TOUCH, #endif TCC(0, 7)); #endif -#ifdef PIN_PA22 +#if defined(PIN_PA22) && !defined(IGNORE_PIN_PA22) PIN(PA22, EXTINT_CHANNEL(6), NO_ADC, NO_TOUCH, SERCOM(3, 0), #ifdef SERCOM5 @@ -388,7 +386,7 @@ PIN(PA22, EXTINT_CHANNEL(6), NO_ADC, NO_TOUCH, TC(4, 0), TCC(0, 4)); #endif -#ifdef PIN_PA23 +#if defined(PIN_PA23) && !defined(IGNORE_PIN_PA23) PIN(PA23, EXTINT_CHANNEL(7), NO_ADC, NO_TOUCH, SERCOM(3, 1), #ifdef SERCOM5 @@ -399,7 +397,7 @@ PIN(PA23, EXTINT_CHANNEL(7), NO_ADC, NO_TOUCH, TC(4, 1), TCC(0, 5)); #endif -#ifdef PIN_PA24 +#if defined(PIN_PA24) && !defined(IGNORE_PIN_PA24) PIN(PA24, EXTINT_CHANNEL(12), NO_ADC, NO_TOUCH, SERCOM(3, 2), #ifdef SERCOM5 @@ -410,7 +408,7 @@ PIN(PA24, EXTINT_CHANNEL(12), NO_ADC, NO_TOUCH, TC(5, 0), TCC(0, 2)); #endif -#ifdef PIN_PA25 +#if defined(PIN_PA25) && !defined(IGNORE_PIN_PA25) PIN(PA25, EXTINT_CHANNEL(13), NO_ADC, NO_TOUCH, SERCOM(3, 3), #ifdef SERCOM5 @@ -421,7 +419,7 @@ PIN(PA25, EXTINT_CHANNEL(13), NO_ADC, NO_TOUCH, TC(5, 1), TCC(1, 3)); #endif -#ifdef PIN_PB22 +#if defined(PIN_PB22) && !defined(IGNORE_PIN_PB22) PIN(PB22, EXTINT_CHANNEL(6), NO_ADC, NO_TOUCH, NO_SERCOM, SERCOM(5, 2), @@ -432,7 +430,7 @@ PIN(PB22, EXTINT_CHANNEL(6), NO_ADC, NO_TOUCH, #endif NO_TIMER); #endif -#ifdef PIN_PB23 +#if defined(PIN_PB23) && !defined(IGNORE_PIN_PB23) PIN(PB23, EXTINT_CHANNEL(7), NO_ADC, NO_TOUCH, NO_SERCOM, SERCOM(5, 3), @@ -443,49 +441,49 @@ PIN(PB23, EXTINT_CHANNEL(7), NO_ADC, NO_TOUCH, #endif NO_TIMER); #endif -#ifdef PIN_PA27 +#if defined(PIN_PA27) && !defined(IGNORE_PIN_PA27) PIN(PA27, EXTINT_CHANNEL(15), NO_ADC, NO_TOUCH, NO_SERCOM, NO_SERCOM, NO_TIMER, NO_TIMER); #endif -#ifdef PIN_PA28 +#if defined(PIN_PA28) && !defined(IGNORE_PIN_PA28) PIN(PA28, EXTINT_CHANNEL(8), NO_ADC, NO_TOUCH, NO_SERCOM, NO_SERCOM, NO_TIMER, NO_TIMER); #endif -#ifdef PIN_PA30 +#if defined(PIN_PA30) && !defined(IGNORE_PIN_PA30) PIN(PA30, EXTINT_CHANNEL(10), NO_ADC, NO_TOUCH, NO_SERCOM, SERCOM(1, 2), TCC(1, 0), NO_TIMER); #endif -#ifdef PIN_PA31 +#if defined(PIN_PA31) && !defined(IGNORE_PIN_PA31) PIN(PA31, EXTINT_CHANNEL(11), NO_ADC, NO_TOUCH, NO_SERCOM, SERCOM(1, 3), TCC(1, 1), NO_TIMER); #endif -#ifdef PIN_PB30 +#if defined(PIN_PB30) && !defined(IGNORE_PIN_PB30) PIN(PB30, EXTINT_CHANNEL(14), NO_ADC, NO_TOUCH, NO_SERCOM, SERCOM(5, 0), TCC(0, 0), TCC(1, 2)); #endif -#ifdef PIN_PB31 +#if defined(PIN_PB31) && !defined(IGNORE_PIN_PB31) PIN(PB31, EXTINT_CHANNEL(15), NO_ADC, NO_TOUCH, NO_SERCOM, SERCOM(5, 1), TCC(0, 1), TCC(1, 3)); #endif -#ifdef PIN_PB00 +#if defined(PIN_PB00) && !defined(IGNORE_PIN_PB00) PIN(PB00, EXTINT_CHANNEL(0), ADC_INPUT(8), TOUCH(6), NO_SERCOM, SERCOM(5, 2), @@ -496,7 +494,7 @@ PIN(PB00, EXTINT_CHANNEL(0), ADC_INPUT(8), TOUCH(6), #endif NO_TIMER); #endif -#ifdef PIN_PB01 +#if defined(PIN_PB01) && !defined(IGNORE_PIN_PB01) PIN(PB01, EXTINT_CHANNEL(1), ADC_INPUT(9), TOUCH(7), NO_SERCOM, SERCOM(5, 3)), @@ -507,7 +505,7 @@ PIN(PB01, EXTINT_CHANNEL(1), ADC_INPUT(9), TOUCH(7), #endif NO_TIMER; #endif -#ifdef PIN_PB02 +#if defined(PIN_PB02) && !defined(IGNORE_PIN_PB02) PIN(PB02, EXTINT_CHANNEL(2), ADC_INPUT(10), TOUCH(8), NO_SERCOM, SERCOM(5, 0), @@ -518,7 +516,7 @@ PIN(PB02, EXTINT_CHANNEL(2), ADC_INPUT(10), TOUCH(8), #endif NO_TIMER); #endif -#ifdef PIN_PB03 +#if defined(PIN_PB03) && !defined(IGNORE_PIN_PB03) PIN(PB03, EXTINT_CHANNEL(3), ADC_INPUT(11), TOUCH(9), NO_SERCOM, SERCOM(5, 1), diff --git a/ports/atmel-samd/samd21_pins.h b/ports/atmel-samd/peripherals/samd21/pins.h similarity index 93% rename from ports/atmel-samd/samd21_pins.h rename to ports/atmel-samd/peripherals/samd21/pins.h index 522563ef11..0b99ce9b36 100644 --- a/ports/atmel-samd/samd21_pins.h +++ b/ports/atmel-samd/peripherals/samd21/pins.h @@ -24,13 +24,14 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_SAMD21_PINS_H -#define MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_SAMD21_PINS_H +// DO NOT include this file directly. Use shared-bindings/microcontroller/Pin.h instead to ensure +// that all necessary includes are already included. + +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_SAMD21_PINS_H +#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_SAMD21_PINS_H #include "include/sam.h" -#include "common-hal/microcontroller/Pin.h" - void reset_pin(uint8_t pin); #define MUX_C 2 @@ -201,4 +202,4 @@ extern const mcu_pin_obj_t pin_PB02; extern const mcu_pin_obj_t pin_PB03; #endif -#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_SAMD21_PINS_H +#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_SAMD21_PINS_H diff --git a/ports/atmel-samd/samd21_peripherals.c b/ports/atmel-samd/peripherals/samd21/sercom.c similarity index 76% rename from ports/atmel-samd/samd21_peripherals.c rename to ports/atmel-samd/peripherals/samd21/sercom.c index 5bbac29655..a27e49e0e5 100644 --- a/ports/atmel-samd/samd21_peripherals.c +++ b/ports/atmel-samd/peripherals/samd21/sercom.c @@ -24,11 +24,9 @@ * THE SOFTWARE. */ -#include "hal/include/hal_adc_sync.h" #include "hpl/gclk/hpl_gclk_base.h" #include "hpl/pm/hpl_pm_base.h" - // The clock initializer values are rather random, so we need to put them in // tables for lookup. We can't compute them. @@ -93,21 +91,3 @@ uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad) { bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad) { return clock_pad == 1 || clock_pad == 3; } - -// Do initialization and calibration setup needed for any use of the ADC. -// The reference and resolution should be set by the caller. -void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance) { - // Turn the clocks on. - _pm_enable_bus_clock(PM_BUS_APBC, ADC); - _gclk_enable_channel(ADC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); - - adc_sync_init(adc, instance, (void *)NULL); - - // Load the factory calibration - hri_adc_write_CALIB_BIAS_CAL_bf(ADC, (*((uint32_t*) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos); - // Bits 7:5 - uint16_t linearity = ((*((uint32_t*) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5; - // Bits 4:0 - linearity |= (*((uint32_t*) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos; - hri_adc_write_CALIB_LINEARITY_CAL_bf(ADC, linearity); -} diff --git a/ports/atmel-samd/peripherals/samd21/timers.c b/ports/atmel-samd/peripherals/samd21/timers.c new file mode 100644 index 0000000000..c93a710867 --- /dev/null +++ b/ports/atmel-samd/peripherals/samd21/timers.c @@ -0,0 +1,75 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "peripherals/timers.h" + +//#include "common-hal/pulseio/PulseOut.h" + +#include "hpl/gclk/hpl_gclk_base.h" + +const uint8_t tcc_cc_num[3] = {4, 2, 2}; +const uint8_t tc_gclk_ids[TC_INST_NUM] = {TC3_GCLK_ID, + TC4_GCLK_ID, + TC5_GCLK_ID, +#ifdef TC6_GCLK_ID + TC6_GCLK_ID, +#endif +#ifdef TC7_GCLK_ID + TC7_GCLK_ID, +#endif + }; +const uint8_t tcc_gclk_ids[3] = {TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID}; + +void turn_on_clocks(bool is_tc, uint8_t index, uint32_t gclk_index) { + uint8_t gclk_id; + if (is_tc) { + gclk_id = tc_gclk_ids[index]; + } else { + gclk_id = tcc_gclk_ids[index]; + } + // Determine the clock slot on the APBC bus. TCC0 is the first and 8 slots in. + uint8_t clock_slot = 8 + index; + // We index TCs starting at zero but in memory they begin at three so we have to add three. + if (is_tc) { + clock_slot += 3; + } + PM->APBCMASK.reg |= 1 << clock_slot; + _gclk_enable_channel(gclk_id, gclk_index); +} + +void tc_set_enable(Tc* tc, bool enable) { + tc->COUNT16.CTRLA.bit.ENABLE = enable; + while (tc->COUNT16.STATUS.bit.SYNCBUSY != 0) { + /* Wait for sync */ + } +} + +void tc_wait_for_sync(Tc* tc) { + while (tc->COUNT16.STATUS.bit.SYNCBUSY != 0) {} +} diff --git a/ports/atmel-samd/peripherals/samd51/adc.c b/ports/atmel-samd/peripherals/samd51/adc.c new file mode 100644 index 0000000000..af6333a949 --- /dev/null +++ b/ports/atmel-samd/peripherals/samd51/adc.c @@ -0,0 +1,61 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hal/include/hal_adc_sync.h" +#include "hpl/gclk/hpl_gclk_base.h" +#include "hri/hri_mclk_d51.h" + +// Do initialization and calibration setup needed for any use of the ADC. +// The reference and resolution should be set by the caller. +void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance) { + // Turn the clocks on. + if (instance == ADC0) { + hri_mclk_set_APBDMASK_ADC0_bit(MCLK); + hri_gclk_write_PCHCTRL_reg(GCLK, ADC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos)); + } else if (instance == ADC1) { + hri_mclk_set_APBDMASK_ADC1_bit(MCLK); + hri_gclk_write_PCHCTRL_reg(GCLK, ADC1_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos)); + } + + adc_sync_init(adc, instance, (void *)NULL); + + // SAMD51 has a CALIB register but doesn't have documented fuses for them. + uint8_t biasrefbuf; + uint8_t biasr2r; + uint8_t biascomp; + if (instance == ADC0) { + biasrefbuf = ((*(uint32_t*) ADC0_FUSES_BIASREFBUF_ADDR) & ADC0_FUSES_BIASREFBUF_Msk) >> ADC0_FUSES_BIASREFBUF_Pos; + biasr2r = ((*(uint32_t*) ADC0_FUSES_BIASR2R_ADDR) & ADC0_FUSES_BIASR2R_Msk) >> ADC0_FUSES_BIASR2R_Pos; + biascomp = ((*(uint32_t*) ADC0_FUSES_BIASCOMP_ADDR) & ADC0_FUSES_BIASCOMP_Msk) >> ADC0_FUSES_BIASCOMP_Pos; + } else { + biasrefbuf = ((*(uint32_t*) ADC1_FUSES_BIASREFBUF_ADDR) & ADC1_FUSES_BIASREFBUF_Msk) >> ADC1_FUSES_BIASREFBUF_Pos; + biasr2r = ((*(uint32_t*) ADC1_FUSES_BIASR2R_ADDR) & ADC1_FUSES_BIASR2R_Msk) >> ADC1_FUSES_BIASR2R_Pos; + biascomp = ((*(uint32_t*) ADC1_FUSES_BIASCOMP_ADDR) & ADC1_FUSES_BIASCOMP_Msk) >> ADC1_FUSES_BIASCOMP_Pos; + } + hri_adc_write_CALIB_BIASREFBUF_bf(instance, biasrefbuf); + hri_adc_write_CALIB_BIASR2R_bf(instance, biasr2r); + hri_adc_write_CALIB_BIASCOMP_bf(instance, biascomp); +} diff --git a/ports/atmel-samd/peripherals/samd51/cache.c b/ports/atmel-samd/peripherals/samd51/cache.c new file mode 100644 index 0000000000..f94dd830c0 --- /dev/null +++ b/ports/atmel-samd/peripherals/samd51/cache.c @@ -0,0 +1,39 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "sam.h" + +// Turn off cache and invalidate all data in it. +void samd_peripherals_disable_and_clear_cache(void) { + CMCC->CTRL.bit.CEN = 0; + while (CMCC->SR.bit.CSTS) {} + CMCC->MAINT0.bit.INVALL = 1; +} + +// Enable cache +void samd_peripherals_enable_cache(void) { + CMCC->CTRL.bit.CEN = 1; +} diff --git a/ports/atmel-samd/peripherals/samd51/clocks.c b/ports/atmel-samd/peripherals/samd51/clocks.c new file mode 100644 index 0000000000..37468a3f7b --- /dev/null +++ b/ports/atmel-samd/peripherals/samd51/clocks.c @@ -0,0 +1,480 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "peripherals/clocks.h" + +#include "hpl_gclk_config.h" + +#include "bindings/samd/Clock.h" +#include "shared-bindings/microcontroller/__init__.h" + +#include "py/runtime.h" + +bool gclk_enabled(uint8_t gclk) { + return GCLK->GENCTRL[gclk].bit.GENEN; +} + +void disable_gclk(uint8_t gclk) { + while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {} + GCLK->GENCTRL[gclk].bit.GENEN = false; + while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {} +} + +void connect_gclk_to_peripheral(uint8_t gclk, uint8_t peripheral) { + GCLK->PCHCTRL[peripheral].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclk); + while(GCLK->SYNCBUSY.reg != 0) {} +} + +void disconnect_gclk_from_peripheral(uint8_t gclk, uint8_t peripheral) { + GCLK->PCHCTRL[peripheral].reg = 0; +} + +static void enable_clock_generator_sync(uint8_t gclk, uint32_t source, uint16_t divisor, bool sync) { + uint32_t divsel = 0; + // The datasheet says 8 bits and max value of 512, how is that possible? + if (divisor > 255) { // Generator 1 has 16 bits + divsel = GCLK_GENCTRL_DIVSEL; + for (int i = 15; i > 0; i--) { + if (divisor & (1 << i)) { + divisor = i - 1; + break; + } + } + } + + GCLK->GENCTRL[gclk].reg = GCLK_GENCTRL_SRC(source) | GCLK_GENCTRL_DIV(divisor) | divsel | GCLK_GENCTRL_OE | GCLK_GENCTRL_GENEN; + if (sync) + while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {} +} + +void enable_clock_generator(uint8_t gclk, uint32_t source, uint16_t divisor) { + enable_clock_generator_sync(gclk, source, divisor, true); +} + +void disable_clock_generator(uint8_t gclk) { + GCLK->GENCTRL[gclk].reg = 0; + while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {} +} + +static void init_clock_source_osculp32k(void) { + // Calibration value is loaded at startup + OSC32KCTRL->OSCULP32K.bit.EN1K = 1; + OSC32KCTRL->OSCULP32K.bit.EN32K = 0; +} + +static void init_clock_source_xosc32k(void) { + OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ONDEMAND | + OSC32KCTRL_XOSC32K_EN1K | + OSC32KCTRL_XOSC32K_XTALEN | + OSC32KCTRL_XOSC32K_ENABLE | + OSC32KCTRL_XOSC32K_CGM(1); +} + +static void init_clock_source_dpll0(void) +{ + GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(5); + OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0) | OSCCTRL_DPLLRATIO_LDR(59); + OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK(0); + OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE; + + while (!(OSCCTRL->Dpll[0].DPLLSTATUS.bit.LOCK || OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY)) {} +} + +void clock_init(void) { + // DFLL48M is enabled by default + + init_clock_source_osculp32k(); + + if (board_has_crystal()) { + init_clock_source_xosc32k(); + OSC32KCTRL->RTCCTRL.bit.RTCSEL = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC1K_Val; + } else { + OSC32KCTRL->RTCCTRL.bit.RTCSEL = OSC32KCTRL_RTCCTRL_RTCSEL_ULP1K_Val; + } + + MCLK->CPUDIV.reg = MCLK_CPUDIV_DIV(1); + + enable_clock_generator_sync(0, GCLK_GENCTRL_SRC_DPLL0_Val, 1, false); + enable_clock_generator_sync(1, GCLK_GENCTRL_SRC_DFLL_Val, 1, false); + enable_clock_generator_sync(4, GCLK_GENCTRL_SRC_DPLL0_Val, 1, false); + enable_clock_generator_sync(5, GCLK_GENCTRL_SRC_DFLL_Val, 24, false); + + init_clock_source_dpll0(); + + // Do this after all static clock init so that they aren't used dynamically. + init_dynamic_clocks(); +} + +static bool clk_enabled(uint8_t clk) { + return GCLK->PCHCTRL[clk].bit.CHEN; +} + +static uint8_t clk_get_generator(uint8_t clk) { + return GCLK->PCHCTRL[clk].bit.GEN; +} + +static uint8_t generator_get_source(uint8_t gen) { + return GCLK->GENCTRL[gen].bit.SRC; +} + +static bool osc_enabled(uint8_t index) { + switch (index) { + case GCLK_SOURCE_XOSC0: + return OSCCTRL->XOSCCTRL[0].bit.ENABLE; + case GCLK_SOURCE_XOSC1: + return OSCCTRL->XOSCCTRL[1].bit.ENABLE; + case GCLK_SOURCE_OSCULP32K: + return true; + case GCLK_SOURCE_XOSC32K: + return OSC32KCTRL->XOSC32K.bit.ENABLE; + case GCLK_SOURCE_DFLL: + return OSCCTRL->DFLLCTRLA.bit.ENABLE; + case GCLK_SOURCE_DPLL0: + return OSCCTRL->Dpll[0].DPLLCTRLA.bit.ENABLE; + case GCLK_SOURCE_DPLL1: + return OSCCTRL->Dpll[1].DPLLCTRLA.bit.ENABLE; + }; + return false; +} + +static uint32_t osc_get_source(uint8_t index) { + uint8_t dpll_index = index - GCLK_SOURCE_DPLL0; + uint32_t refclk = OSCCTRL->Dpll[dpll_index].DPLLCTRLB.bit.REFCLK; + switch (refclk) { + case 0x0: + return generator_get_source(GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0 + dpll_index].bit.GEN); + case 0x1: + return GCLK_SOURCE_XOSC32K; + case 0x2: + return GCLK_SOURCE_XOSC0; + case 0x3: + return GCLK_SOURCE_XOSC1; + } + return 0; +} + +static uint32_t osc_get_frequency(uint8_t index); + +static uint32_t generator_get_frequency(uint8_t gen) { + uint8_t src = GCLK->GENCTRL[gen].bit.SRC; + uint32_t div; + if (GCLK->GENCTRL[gen].bit.DIVSEL) { + div = 1 << (GCLK->GENCTRL[gen].bit.DIV + 1); + } else { + div = GCLK->GENCTRL[gen].bit.DIV; + if (!div) + div = 1; + } + + return osc_get_frequency(src) / div; +} + +static uint32_t dpll_get_frequency(uint8_t index) { + uint8_t dpll_index = index - GCLK_SOURCE_DPLL0; + uint32_t refclk = OSCCTRL->Dpll[dpll_index].DPLLCTRLB.bit.REFCLK; + uint32_t freq; + + switch (refclk) { + case 0x0: // GCLK + freq = generator_get_frequency(GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0 + dpll_index].bit.GEN); + break; + case 0x1: // XOSC32 + freq = 32768; + break; + case 0x2: // XOSC0 + case 0x3: // XOSC1 + default: + return 0; // unknown + } + + return (freq * (OSCCTRL->Dpll[dpll_index].DPLLRATIO.bit.LDR + 1)) + + (freq * OSCCTRL->Dpll[dpll_index].DPLLRATIO.bit.LDRFRAC / 32); +} + +static uint32_t osc_get_frequency(uint8_t index) { + switch (index) { + case GCLK_SOURCE_XOSC0: + case GCLK_SOURCE_XOSC1: + return 0; // unknown + case GCLK_SOURCE_OSCULP32K: + case GCLK_SOURCE_XOSC32K: + return 32768; + case GCLK_SOURCE_DFLL: + return 48000000; + case GCLK_SOURCE_DPLL0: + case GCLK_SOURCE_DPLL1: + return dpll_get_frequency(index); + } + return 0; +} + +bool clock_get_enabled(uint8_t type, uint8_t index) { + if (type == 0) + return osc_enabled(index); + if (type == 1) + return clk_enabled(index); + if (type == 2) + return SysTick->CTRL & SysTick_CTRL_ENABLE_Msk; + return false; +} + +bool clock_get_parent(uint8_t type, uint8_t index, uint8_t *p_type, uint8_t *p_index) { + if (type == 0 && osc_enabled(index)) { + if (index == GCLK_SOURCE_DPLL0 || index == GCLK_SOURCE_DPLL1) { + *p_type = 0; + *p_index = osc_get_source(index); + return true; + } + return false; + } + if (type == 1 && index <= 47 && clk_enabled(index)) { + *p_type = 0; + *p_index = generator_get_source(clk_get_generator(index)); + return true; + } + if (type == 2) { + switch (index) { + case 0: + case 1: + *p_type = 0; + *p_index = generator_get_source(0); + return true; + case 2: + *p_type = 0; + switch (OSC32KCTRL->RTCCTRL.bit.RTCSEL) { + case 0: + case 1: + *p_index = GCLK_SOURCE_OSCULP32K; + return true; + case 4: + case 5: + *p_index = GCLK_SOURCE_XOSC32K; + return true; + } + return false; + } + } + return false; +} + +uint32_t clock_get_frequency(uint8_t type, uint8_t index) { + if (type == 0) { + return osc_get_frequency(index); + } + if (type == 1 && index <= 47 && clk_enabled(index)) { + return generator_get_frequency(clk_get_generator(index)); + } + if (type == 2) { + switch (index) { + case 0: + return clock_get_frequency(0, generator_get_source(0)) / SysTick->LOAD; + case 1: + return clock_get_frequency(0, generator_get_source(0)) / MCLK->CPUDIV.bit.DIV; + case 2: + switch (OSC32KCTRL->RTCCTRL.bit.RTCSEL) { + case 0: + case 4: + return 1024; + case 1: + case 5: + return 32768; + } + } + } + return 0; +} + +uint32_t clock_get_calibration(uint8_t type, uint8_t index) { + if (type == 0) { + switch (index) { + case GCLK_SOURCE_OSCULP32K: + return OSC32KCTRL->OSCULP32K.bit.CALIB; + }; + } + if (type == 2 && index == 0) { + return SysTick->LOAD + 1; + } + return 0; +} + +int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val) { + if (type == 0) { + switch (index) { + case GCLK_SOURCE_OSCULP32K: + if (val > 0x3f) + return -1; + OSC32KCTRL->OSCULP32K.bit.CALIB = val; + return 0; + }; + } + if (type == 2 && index == 0) { + if (val < 0x1000 || val > 0x1000000) + return -1; + SysTick->LOAD = val - 1; + return 0; + } + return -2; +} + + +void save_usb_clock_calibration(void) { +} + +#include +#include +#include +#include +#include +#include +#include + +CLOCK_SOURCE(XOSC0); +CLOCK_SOURCE(XOSC1); +CLOCK_SOURCE(GCLKIN); +CLOCK_SOURCE(GCLKGEN1); +CLOCK_SOURCE(OSCULP32K); +CLOCK_SOURCE(XOSC32K); +CLOCK_SOURCE(DFLL); +CLOCK_SOURCE(DPLL0); +CLOCK_SOURCE(DPLL1); + +CLOCK_GCLK_(OSCCTRL, DFLL48); +CLOCK_GCLK_(OSCCTRL, FDPLL0); +CLOCK_GCLK_(OSCCTRL, FDPLL1); +CLOCK_GCLK_(OSCCTRL, FDPLL032K); // GCLK_OSCCTRL_FDPLL1_32K, GCLK_SDHC0_SLOW, GCLK_SDHC1_SLOW, GCLK_SERCOM[0..7]_SLOW +CLOCK_GCLK(EIC); +CLOCK_GCLK_(FREQM, MSR); +// 6: GCLK_FREQM_REF +CLOCK_GCLK_(SERCOM0, CORE); +CLOCK_GCLK_(SERCOM1, CORE); +CLOCK(TC0_TC1, 1, 9); +CLOCK_GCLK(USB); +CLOCK_GCLK_(EVSYS, 0); +CLOCK_GCLK_(EVSYS, 1); +CLOCK_GCLK_(EVSYS, 2); +CLOCK_GCLK_(EVSYS, 3); +CLOCK_GCLK_(EVSYS, 4); +CLOCK_GCLK_(EVSYS, 5); +CLOCK_GCLK_(EVSYS, 6); +CLOCK_GCLK_(EVSYS, 7); +CLOCK_GCLK_(EVSYS, 8); +CLOCK_GCLK_(EVSYS, 9); +CLOCK_GCLK_(EVSYS, 10); +CLOCK_GCLK_(EVSYS, 11); +CLOCK_GCLK_(SERCOM2, CORE); +CLOCK_GCLK_(SERCOM3, CORE); +CLOCK(TCC0_TCC1, 1, 25); +CLOCK(TC2_TC3, 1, 26); +CLOCK_GCLK(CAN0); +CLOCK_GCLK(CAN1); +CLOCK(TCC2_TCC3, 1, 29); +CLOCK(TC4_TC5, 1, 30); +CLOCK_GCLK(PDEC); +CLOCK_GCLK(AC); +CLOCK_GCLK(CCL); +CLOCK_GCLK_(SERCOM4, CORE); +CLOCK_GCLK_(SERCOM5, CORE); +CLOCK_GCLK_(SERCOM6, CORE); +CLOCK_GCLK_(SERCOM7, CORE); +CLOCK_GCLK(TCC4); +CLOCK(TC6_TC7, 1, 39); +CLOCK_GCLK(ADC0); +CLOCK_GCLK(ADC1); +CLOCK_GCLK(DAC); +CLOCK_GCLK_(I2S, 0); +CLOCK_GCLK_(I2S, 1); +CLOCK_GCLK(SDHC0); +CLOCK_GCLK(SDHC1); +// 47: GCLK_CM4_TRACE + +CLOCK(SYSTICK, 2, 0); +CLOCK(CPU, 2, 1); +CLOCK(RTC, 2, 2); + + +STATIC const mp_rom_map_elem_t samd_clock_global_dict_table[] = { + CLOCK_ENTRY(XOSC0), + CLOCK_ENTRY(XOSC1), + CLOCK_ENTRY(GCLKIN), + CLOCK_ENTRY(GCLKGEN1), + CLOCK_ENTRY(OSCULP32K), + CLOCK_ENTRY(XOSC32K), + CLOCK_ENTRY(DFLL), + CLOCK_ENTRY(DPLL0), + CLOCK_ENTRY(DPLL1), + + CLOCK_ENTRY_(OSCCTRL, DFLL48), + CLOCK_ENTRY_(OSCCTRL, FDPLL0), + CLOCK_ENTRY_(OSCCTRL, FDPLL1), + CLOCK_ENTRY_(OSCCTRL, FDPLL032K), + CLOCK_ENTRY(EIC), + CLOCK_ENTRY_(FREQM, MSR), + CLOCK_ENTRY_(SERCOM0, CORE), + CLOCK_ENTRY_(SERCOM1, CORE), + CLOCK_ENTRY(TC0_TC1), + CLOCK_ENTRY(USB), + CLOCK_ENTRY_(EVSYS, 0), + CLOCK_ENTRY_(EVSYS, 1), + CLOCK_ENTRY_(EVSYS, 2), + CLOCK_ENTRY_(EVSYS, 3), + CLOCK_ENTRY_(EVSYS, 4), + CLOCK_ENTRY_(EVSYS, 5), + CLOCK_ENTRY_(EVSYS, 6), + CLOCK_ENTRY_(EVSYS, 7), + CLOCK_ENTRY_(EVSYS, 8), + CLOCK_ENTRY_(EVSYS, 9), + CLOCK_ENTRY_(EVSYS, 10), + CLOCK_ENTRY_(EVSYS, 11), + CLOCK_ENTRY_(SERCOM2, CORE), + CLOCK_ENTRY_(SERCOM3, CORE), + CLOCK_ENTRY(TCC0_TCC1), + CLOCK_ENTRY(TC2_TC3), + CLOCK_ENTRY(CAN0), + CLOCK_ENTRY(CAN1), + CLOCK_ENTRY(TCC2_TCC3), + CLOCK_ENTRY(TC4_TC5), + CLOCK_ENTRY(PDEC), + CLOCK_ENTRY(AC), + CLOCK_ENTRY(CCL), + CLOCK_ENTRY_(SERCOM4, CORE), + CLOCK_ENTRY_(SERCOM5, CORE), + CLOCK_ENTRY_(SERCOM6, CORE), + CLOCK_ENTRY_(SERCOM7, CORE), + CLOCK_ENTRY(TCC4), + CLOCK_ENTRY(TC6_TC7), + CLOCK_ENTRY(ADC0), + CLOCK_ENTRY(ADC1), + CLOCK_ENTRY(DAC), + CLOCK_ENTRY_(I2S, 0), + CLOCK_ENTRY_(I2S, 1), + CLOCK_ENTRY(SDHC0), + CLOCK_ENTRY(SDHC1), + + CLOCK_ENTRY(SYSTICK), + CLOCK_ENTRY(CPU), + CLOCK_ENTRY(RTC), +}; +MP_DEFINE_CONST_DICT(samd_clock_globals, samd_clock_global_dict_table); diff --git a/ports/atmel-samd/peripherals/samd51/dma.c b/ports/atmel-samd/peripherals/samd51/dma.c new file mode 100644 index 0000000000..ccb35aaf65 --- /dev/null +++ b/ports/atmel-samd/peripherals/samd51/dma.c @@ -0,0 +1,94 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "peripherals/dma.h" + +#include + +#include "py/gc.h" +#include "py/mpstate.h" + +#include "hal/utils/include/utils.h" + +#include "shared-bindings/microcontroller/__init__.h" + +uint8_t sercom_index(Sercom* sercom) { + const Sercom* sercoms[SERCOM_INST_NUM] = SERCOM_INSTS; + for (uint8_t i = 0; i < SERCOM_INST_NUM; i++) { + if (sercoms[i] == sercom) { + return i; + } + } + return 0; +} + +void dma_configure(uint8_t channel_number, uint8_t trigsrc, bool output_event) { + DmacChannel* channel = &DMAC->Channel[channel_number]; + channel->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; + channel->CHCTRLA.reg = DMAC_CHCTRLA_SWRST; + if (output_event) { + channel->CHEVCTRL.reg = DMAC_CHEVCTRL_EVOE; + } + channel->CHCTRLA.reg = DMAC_CHCTRLA_TRIGSRC(trigsrc) | + DMAC_CHCTRLA_TRIGACT_BURST | + DMAC_CHCTRLA_BURSTLEN_SINGLE; +} + +void dma_enable_channel(uint8_t channel_number) { + DmacChannel* channel = &DMAC->Channel[channel_number]; + channel->CHCTRLA.bit.ENABLE = true; + // Clear any previous interrupts. + channel->CHINTFLAG.reg = DMAC_CHINTFLAG_MASK; +} + +void dma_disable_channel(uint8_t channel_number) { + DmacChannel* channel = &DMAC->Channel[channel_number]; + channel->CHCTRLA.bit.ENABLE = false; +} + +void dma_suspend_channel(uint8_t channel_number) { + DmacChannel* channel = &DMAC->Channel[channel_number]; + channel->CHCTRLB.reg = DMAC_CHCTRLB_CMD_SUSPEND; +} + +void dma_resume_channel(uint8_t channel_number) { + DmacChannel* channel = &DMAC->Channel[channel_number]; + channel->CHCTRLB.reg = DMAC_CHCTRLB_CMD_RESUME; +} + +bool dma_channel_enabled(uint8_t channel_number) { + DmacChannel* channel = &DMAC->Channel[channel_number]; + return channel->CHCTRLA.bit.ENABLE; +} + +uint8_t dma_transfer_status(uint8_t channel_number) { + DmacChannel* channel = &DMAC->Channel[channel_number]; + return channel->CHINTFLAG.reg; +} + +bool dma_channel_free(uint8_t channel_number) { + DmacChannel* channel = &DMAC->Channel[channel_number]; + return channel->CHSTATUS.reg == 0; +} diff --git a/ports/atmel-samd/peripherals/samd51/events.c b/ports/atmel-samd/peripherals/samd51/events.c new file mode 100644 index 0000000000..5ea2c87e69 --- /dev/null +++ b/ports/atmel-samd/peripherals/samd51/events.c @@ -0,0 +1,88 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "peripherals/events.h" + +#include "peripherals/clocks.h" + +#include "py/runtime.h" + +#include "hri/hri_mclk_d51.h" + +void turn_on_event_system(void) { + hri_mclk_set_APBBMASK_EVSYS_bit(MCLK); +} + +void reset_event_system(void) { + EVSYS->CTRLA.bit.SWRST = true; + hri_mclk_clear_APBBMASK_EVSYS_bit(MCLK); +} + +bool event_channel_free(uint8_t channel) { + uint8_t generator; + generator = EVSYS->Channel[channel].CHANNEL.bit.EVGEN; + return generator == 0; +} + +void disable_event_channel(uint8_t channel_number) { + EVSYS->Channel[channel_number].CHANNEL.reg = 0; +} + +void disable_event_user(uint8_t user_number) { + EVSYS->USER[user_number].reg = 0; +} + +void connect_event_user_to_channel(uint8_t user, uint8_t channel) { + EVSYS->USER[user].reg = channel + 1; +} + +void init_async_event_channel(uint8_t channel, uint8_t generator) { + EVSYS->Channel[channel].CHANNEL.reg = EVSYS_CHANNEL_EVGEN(generator) | EVSYS_CHANNEL_PATH_ASYNCHRONOUS; +} + +void init_event_channel_interrupt(uint8_t channel, uint8_t gclk, uint8_t generator) { + connect_gclk_to_peripheral(gclk, EVSYS_GCLK_ID_0 + channel); + EVSYS->Channel[channel].CHANNEL.reg = EVSYS_CHANNEL_EVGEN(generator) | + EVSYS_CHANNEL_PATH_SYNCHRONOUS | + EVSYS_CHANNEL_EDGSEL_RISING_EDGE; + EVSYS->Channel[channel].CHINTFLAG.reg = EVSYS_CHINTFLAG_EVD | EVSYS_CHINTFLAG_OVR; + EVSYS->Channel[channel].CHINTENSET.reg = EVSYS_CHINTENSET_EVD | EVSYS_CHINTENSET_OVR; +} + +bool event_interrupt_active(uint8_t channel) { + bool active = false; + active = EVSYS->Channel[channel].CHINTFLAG.bit.EVD; + // Only clear if we know its active, otherwise there is the possibility it becomes after we + // check but before we clear. + if (active) { + EVSYS->Channel[channel].CHINTFLAG.reg = EVSYS_CHINTFLAG_EVD | EVSYS_CHINTFLAG_OVR; + } + return active; +} + +bool event_interrupt_overflow(uint8_t channel) { + return EVSYS->Channel[channel].CHINTFLAG.bit.OVR; +} diff --git a/ports/atmel-samd/peripherals/samd51/external_interrupts.c b/ports/atmel-samd/peripherals/samd51/external_interrupts.c new file mode 100644 index 0000000000..6006d480e6 --- /dev/null +++ b/ports/atmel-samd/peripherals/samd51/external_interrupts.c @@ -0,0 +1,132 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "peripherals/external_interrupts.h" + +#include "peripherals/clocks.h" +#include "sam.h" + +void turn_on_external_interrupt_controller(void) { + MCLK->APBAMASK.bit.EIC_ = true; + + // We use the 48mhz clock to lightly filter the incoming pulse to reduce spurious interrupts. + connect_gclk_to_peripheral(GCLK_PCHCTRL_GEN_GCLK1_Val, EIC_GCLK_ID); + eic_set_enable(true); +} + +void turn_off_external_interrupt_controller(void) { + eic_set_enable(false); + MCLK->APBAMASK.bit.EIC_ = false; + disconnect_gclk_from_peripheral(GCLK_PCHCTRL_GEN_GCLK1_Val, EIC_GCLK_ID); +} + +void turn_on_cpu_interrupt(uint8_t eic_channel) { + // Ignore the channel since the CPU interrupt line is shared. + (void) eic_channel; + + NVIC_DisableIRQ(EIC_0_IRQn + eic_channel); + NVIC_ClearPendingIRQ(EIC_0_IRQn + eic_channel); + NVIC_EnableIRQ(EIC_0_IRQn + eic_channel); +} + +bool eic_get_enable(void) { + return EIC->CTRLA.bit.ENABLE; +} + +void eic_set_enable(bool value) { + EIC->CTRLA.bit.ENABLE = value; + while (EIC->SYNCBUSY.bit.ENABLE != 0) {} + // This won't actually block long enough in Rev A of SAMD51 and will miss edges in the first + // three cycles of the peripheral clock. See the errata for details. It shouldn't impact us. +} + +void eic_reset(void) { + EIC->CTRLA.bit.SWRST = true; + while (EIC->SYNCBUSY.bit.SWRST != 0) {} + // This won't actually block long enough in Rev A of SAMD51 and will miss edges in the first + // three cycles of the peripheral clock. See the errata for details. It shouldn't impact us. + for (int i = 0; i < EIC_EXTINT_NUM; i++) { + set_eic_channel_data(i, NULL); + NVIC_DisableIRQ(EIC_0_IRQn + i); + NVIC_ClearPendingIRQ(EIC_0_IRQn + i); + } +} + +bool eic_channel_free(uint8_t eic_channel) { + uint32_t mask = 1 << eic_channel; + return get_eic_channel_data(eic_channel) == NULL && + (EIC->INTENSET.bit.EXTINT & mask) == 0 && + (EIC->EVCTRL.bit.EXTINTEO & mask) == 0; +} + +void EIC_0_Handler(void) { + external_interrupt_handler(0); +} +void EIC_1_Handler(void) { + external_interrupt_handler(1); +} +void EIC_2_Handler(void) { + external_interrupt_handler(2); +} +void EIC_3_Handler(void) { + external_interrupt_handler(3); +} +void EIC_4_Handler(void) { + external_interrupt_handler(4); +} +void EIC_5_Handler(void) { + external_interrupt_handler(5); +} +void EIC_6_Handler(void) { + external_interrupt_handler(6); +} +void EIC_7_Handler(void) { + external_interrupt_handler(7); +} +void EIC_8_Handler(void) { + external_interrupt_handler(8); +} +void EIC_9_Handler(void) { + external_interrupt_handler(9); +} +void EIC_10_Handler(void) { + external_interrupt_handler(10); +} +void EIC_11_Handler(void) { + external_interrupt_handler(11); +} +void EIC_12_Handler(void) { + external_interrupt_handler(12); +} +void EIC_13_Handler(void) { + external_interrupt_handler(13); +} +void EIC_14_Handler(void) { + external_interrupt_handler(14); +} +void EIC_15_Handler(void) { + external_interrupt_handler(15); +} diff --git a/ports/atmel-samd/i2s.c b/ports/atmel-samd/peripherals/samd51/i2s.c similarity index 68% rename from ports/atmel-samd/i2s.c rename to ports/atmel-samd/peripherals/samd51/i2s.c index 663ecdd1dc..97ce13f7d9 100644 --- a/ports/atmel-samd/i2s.c +++ b/ports/atmel-samd/peripherals/samd51/i2s.c @@ -24,53 +24,22 @@ * THE SOFTWARE. */ -#include "i2s.h" +#include "peripherals/i2s.h" -#include "clocks.h" +#include "peripherals/clocks.h" #include "hpl/gclk/hpl_gclk_base.h" -#ifdef SAMD21 -#include "hpl/pm/hpl_pm_base.h" -#endif void turn_on_i2s(void) { // Make sure the I2S peripheral is running so we can see if the resources we need are free. - #ifdef SAMD51 hri_mclk_set_APBDMASK_I2S_bit(MCLK); // Connect the clock units to the 2mhz clock by default. They can't reset without it. connect_gclk_to_peripheral(5, I2S_GCLK_ID_0); connect_gclk_to_peripheral(5, I2S_GCLK_ID_1); - #endif - - #ifdef SAMD21 - _pm_enable_bus_clock(PM_BUS_APBC, I2S); - #endif -} - -void i2s_set_enable(bool enable) { - while (I2S->SYNCBUSY.bit.ENABLE == 1) {} - I2S->CTRLA.bit.ENABLE = enable; - while (I2S->SYNCBUSY.bit.ENABLE == 1) {} -} - -void i2s_set_clock_unit_enable(uint8_t clock_unit, bool enable) { - while ((I2S->SYNCBUSY.vec.CKEN & (1 << clock_unit)) != 0) {} - I2S->CTRLA.vec.CKEN = 1 << clock_unit; - while ((I2S->SYNCBUSY.vec.CKEN & (1 << clock_unit)) != 0) {} } void i2s_set_serializer_enable(uint8_t serializer, bool enable) { - #ifdef SAMD21 - while ((I2S->SYNCBUSY.vec.SEREN & (1 << serializer)) != 0) {} - if (enable) { - I2S->CTRLA.vec.SEREN = 1 << serializer; - } else { - I2S->CTRLA.vec.SEREN &= ~(1 << serializer); - } - while ((I2S->SYNCBUSY.vec.SEREN & (1 << serializer)) != 0) {} - #endif - #ifdef SAMD51 if (serializer == 0) { while (I2S->SYNCBUSY.bit.TXEN == 1) {} I2S->CTRLA.bit.TXEN = enable; @@ -80,5 +49,4 @@ void i2s_set_serializer_enable(uint8_t serializer, bool enable) { I2S->CTRLA.bit.RXEN = enable; while (I2S->SYNCBUSY.bit.RXEN == 1) {} } - #endif } diff --git a/ports/atmel-samd/samd51_pins.c b/ports/atmel-samd/peripherals/samd51/pins.c similarity index 99% rename from ports/atmel-samd/samd51_pins.c rename to ports/atmel-samd/peripherals/samd51/pins.c index 6d597b6e1a..1c52d35a24 100644 --- a/ports/atmel-samd/samd51_pins.c +++ b/ports/atmel-samd/peripherals/samd51/pins.c @@ -26,8 +26,6 @@ #include "shared-bindings/microcontroller/Pin.h" -#include "samd51_pins.h" - #define SERCOM(sercom_index, p_pad) \ { \ .index = sercom_index, \ diff --git a/ports/atmel-samd/samd51_pins.h b/ports/atmel-samd/peripherals/samd51/pins.h similarity index 98% rename from ports/atmel-samd/samd51_pins.h rename to ports/atmel-samd/peripherals/samd51/pins.h index c9ffacc24b..b9a05a3459 100644 --- a/ports/atmel-samd/samd51_pins.h +++ b/ports/atmel-samd/peripherals/samd51/pins.h @@ -24,13 +24,14 @@ * THE SOFTWARE. */ +// DO NOT include this file directly. Use shared-bindings/microcontroller/Pin.h instead to ensure +// that all necessary includes are already included. + #ifndef MICROPY_INCLUDED_ATMEL_SAMD_SAMD51_PINS_H #define MICROPY_INCLUDED_ATMEL_SAMD_SAMD51_PINS_H #include "include/sam.h" -#include "common-hal/microcontroller/Pin.h" - void reset_pin(uint8_t pin); #define MUX_C 2 diff --git a/ports/atmel-samd/samd51_peripherals.c b/ports/atmel-samd/peripherals/samd51/sercom.c similarity index 67% rename from ports/atmel-samd/samd51_peripherals.c rename to ports/atmel-samd/peripherals/samd51/sercom.c index 5772b8e0ab..6d0a02fbd7 100644 --- a/ports/atmel-samd/samd51_peripherals.c +++ b/ports/atmel-samd/peripherals/samd51/sercom.c @@ -131,47 +131,3 @@ uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad) { bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad) { return clock_pad == 1; } - -// Do initialization and calibration setup needed for any use of the ADC. -// The reference and resolution should be set by the caller. -void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance) { - // Turn the clocks on. - if (instance == ADC0) { - hri_mclk_set_APBDMASK_ADC0_bit(MCLK); - hri_gclk_write_PCHCTRL_reg(GCLK, ADC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos)); - } else if (instance == ADC1) { - hri_mclk_set_APBDMASK_ADC1_bit(MCLK); - hri_gclk_write_PCHCTRL_reg(GCLK, ADC1_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos)); - } - - adc_sync_init(adc, instance, (void *)NULL); - - // SAMD51 has a CALIB register but doesn't have documented fuses for them. - uint8_t biasrefbuf; - uint8_t biasr2r; - uint8_t biascomp; - if (instance == ADC0) { - biasrefbuf = ((*(uint32_t*) ADC0_FUSES_BIASREFBUF_ADDR) & ADC0_FUSES_BIASREFBUF_Msk) >> ADC0_FUSES_BIASREFBUF_Pos; - biasr2r = ((*(uint32_t*) ADC0_FUSES_BIASR2R_ADDR) & ADC0_FUSES_BIASR2R_Msk) >> ADC0_FUSES_BIASR2R_Pos; - biascomp = ((*(uint32_t*) ADC0_FUSES_BIASCOMP_ADDR) & ADC0_FUSES_BIASCOMP_Msk) >> ADC0_FUSES_BIASCOMP_Pos; - } else { - biasrefbuf = ((*(uint32_t*) ADC1_FUSES_BIASREFBUF_ADDR) & ADC1_FUSES_BIASREFBUF_Msk) >> ADC1_FUSES_BIASREFBUF_Pos; - biasr2r = ((*(uint32_t*) ADC1_FUSES_BIASR2R_ADDR) & ADC1_FUSES_BIASR2R_Msk) >> ADC1_FUSES_BIASR2R_Pos; - biascomp = ((*(uint32_t*) ADC1_FUSES_BIASCOMP_ADDR) & ADC1_FUSES_BIASCOMP_Msk) >> ADC1_FUSES_BIASCOMP_Pos; - } - hri_adc_write_CALIB_BIASREFBUF_bf(instance, biasrefbuf); - hri_adc_write_CALIB_BIASR2R_bf(instance, biasr2r); - hri_adc_write_CALIB_BIASCOMP_bf(instance, biascomp); -} - -// Turn off cache and invalidate all data in it. -void samd_peripherals_disable_and_clear_cache(void) { - CMCC->CTRL.bit.CEN = 0; - while (CMCC->SR.bit.CSTS) {} - CMCC->MAINT0.bit.INVALL = 1; -} - -// Enable cache -void samd_peripherals_enable_cache(void) { - CMCC->CTRL.bit.CEN = 1; -} diff --git a/ports/atmel-samd/timers.c b/ports/atmel-samd/peripherals/samd51/timers.c similarity index 56% rename from ports/atmel-samd/timers.c rename to ports/atmel-samd/peripherals/samd51/timers.c index 33518b782f..f25dbc0e41 100644 --- a/ports/atmel-samd/timers.c +++ b/ports/atmel-samd/peripherals/samd51/timers.c @@ -27,36 +27,10 @@ #include #include -#include "timers.h" +#include "peripherals/timers.h" -#include "common-hal/pulseio/PulseOut.h" - -#ifdef SAMD21 -#include "hpl/gclk/hpl_gclk_base.h" -#endif - -#ifdef SAMD51 #include "hri/hri_gclk_d51.h" -#endif -const uint16_t prescaler[8] = {1, 2, 4, 8, 16, 64, 256, 1024}; - -// This bitmask keeps track of which channels of a TCC are currently claimed. -#ifdef SAMD21 -const uint8_t tcc_cc_num[3] = {4, 2, 2}; -const uint8_t tc_gclk_ids[TC_INST_NUM] = {TC3_GCLK_ID, - TC4_GCLK_ID, - TC5_GCLK_ID, -#ifdef TC6_GCLK_ID - TC6_GCLK_ID, -#endif -#ifdef TC7_GCLK_ID - TC7_GCLK_ID, -#endif - }; -const uint8_t tcc_gclk_ids[3] = {TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID}; -#endif -#ifdef SAMD51 const uint8_t tcc_cc_num[5] = {6, 4, 3, 2, 2}; const uint8_t tc_gclk_ids[TC_INST_NUM] = {TC0_GCLK_ID, TC1_GCLK_ID, @@ -85,36 +59,6 @@ const uint8_t tcc_gclk_ids[TCC_INST_NUM] = {TCC0_GCLK_ID, TCC4_GCLK_ID #endif }; -#endif -Tc* const tc_insts[TC_INST_NUM] = TC_INSTS; -Tcc* const tcc_insts[TCC_INST_NUM] = TCC_INSTS; - -IRQn_Type const tc_irq[TC_INST_NUM] = { -#ifdef TC0 - TC0_IRQn, -#endif -#ifdef TC1 - TC1_IRQn, -#endif -#ifdef TC2 - TC2_IRQn, -#endif -#ifdef TC3 - TC3_IRQn, -#endif -#ifdef TC4 - TC4_IRQn, -#endif -#ifdef TC5 - TC5_IRQn, -#endif -#ifdef TC6 - TC6_IRQn, -#endif -#ifdef TC7 - TC7_IRQn, -#endif -}; void turn_on_clocks(bool is_tc, uint8_t index, uint32_t gclk_index) { uint8_t gclk_id; @@ -124,7 +68,6 @@ void turn_on_clocks(bool is_tc, uint8_t index, uint32_t gclk_index) { gclk_id = tcc_gclk_ids[index]; } // Turn on the clocks for the peripherals. - #ifdef SAMD51 if (is_tc) { switch (index) { case 0: @@ -180,122 +123,15 @@ void turn_on_clocks(bool is_tc, uint8_t index, uint32_t gclk_index) { hri_gclk_write_PCHCTRL_reg(GCLK, gclk_id, gclk_index | (1 << GCLK_PCHCTRL_CHEN_Pos)); - #endif - - #ifdef SAMD21 - // Determine the clock slot on the APBC bus. TCC0 is the first and 8 slots in. - uint8_t clock_slot = 8 + index; - // We index TCs starting at zero but in memory they begin at three so we have to add three. - if (is_tc) { - clock_slot += 3; - } - PM->APBCMASK.reg |= 1 << clock_slot; - _gclk_enable_channel(gclk_id, gclk_index); - #endif } void tc_set_enable(Tc* tc, bool enable) { tc->COUNT16.CTRLA.bit.ENABLE = enable; - #ifdef SAMD21 - while (tc->COUNT16.STATUS.bit.SYNCBUSY != 0) { - /* Wait for sync */ - } - #endif - #ifdef SAMD51 while (tc->COUNT16.SYNCBUSY.bit.ENABLE != 0) { /* Wait for sync */ } - #endif -} - -void tc_enable_interrupts(uint8_t tc_index) { - NVIC_DisableIRQ(tc_irq[tc_index]); - NVIC_ClearPendingIRQ(tc_irq[tc_index]); - NVIC_EnableIRQ(tc_irq[tc_index]); -} - -void tc_disable_interrupts(uint8_t tc_index) { - NVIC_DisableIRQ(tc_irq[tc_index]); - NVIC_ClearPendingIRQ(tc_irq[tc_index]); -} - -void tcc_set_enable(Tcc* tcc, bool enable) { - tcc->CTRLA.bit.ENABLE = enable; - while (tcc->SYNCBUSY.bit.ENABLE != 0) { - /* Wait for sync */ - } } void tc_wait_for_sync(Tc* tc) { - #ifdef SAMD21 - while (tc->COUNT16.STATUS.bit.SYNCBUSY != 0) {} - #endif - #ifdef SAMD51 while (tc->COUNT16.SYNCBUSY.reg != 0) {} - #endif } - -void tc_reset(Tc* tc) { - tc->COUNT16.CTRLA.bit.SWRST = 1; - while (tc->COUNT16.CTRLA.bit.SWRST == 1) { - } -} - -void shared_timer_handler(bool is_tc, uint8_t index) { - // Add calls to interrupt handlers for specific functionality here. - if (is_tc) { - pulseout_interrupt_handler(index); - } -} - -#ifdef SAMD51 -#define TC_OFFSET 0 -#endif -#ifdef SAMD21 -#define TC_OFFSET 3 -#endif - -void TCC0_Handler(void) { - shared_timer_handler(false, 0); -} -void TCC1_Handler(void) { - shared_timer_handler(false, 1); -} -void TCC2_Handler(void) { - shared_timer_handler(false, 2); -} -// TC0 - TC2 only exist on the SAMD51 -#ifdef TC0 -void TC0_Handler(void) { - shared_timer_handler(true, 0); -} -#endif -#ifdef TC1 -void TC1_Handler(void) { - shared_timer_handler(true, 1); -} -#endif -#ifdef TC2 -void TC2_Handler(void) { - shared_timer_handler(true, 2); -} -#endif -void TC3_Handler(void) { - shared_timer_handler(true, 3 - TC_OFFSET); -} -void TC4_Handler(void) { - shared_timer_handler(true, 4 - TC_OFFSET); -} -void TC5_Handler(void) { - shared_timer_handler(true, 5 - TC_OFFSET); -} -#ifdef TC6 -void TC6_Handler(void) { - shared_timer_handler(true, 6 - TC_OFFSET); -} -#endif -#ifdef TC7 -void TC7_Handler(void) { - shared_timer_handler(true, 7 - TC_OFFSET); -} -#endif diff --git a/ports/atmel-samd/peripherals.c b/ports/atmel-samd/peripherals/sercom.c similarity index 98% rename from ports/atmel-samd/peripherals.c rename to ports/atmel-samd/peripherals/sercom.c index c75a1f43b5..04c1fd008d 100644 --- a/ports/atmel-samd/peripherals.c +++ b/ports/atmel-samd/peripherals/sercom.c @@ -24,7 +24,7 @@ * THE SOFTWARE. */ -#include "peripherals.h" +#include "peripherals/sercom.h" #include "hpl_sercom_config.h" diff --git a/ports/atmel-samd/peripherals.h b/ports/atmel-samd/peripherals/sercom.h similarity index 79% rename from ports/atmel-samd/peripherals.h rename to ports/atmel-samd/peripherals/sercom.h index 8a07c00457..66ad1a403f 100644 --- a/ports/atmel-samd/peripherals.h +++ b/ports/atmel-samd/peripherals/sercom.h @@ -24,24 +24,19 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_H -#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_H +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_SPI_H +#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_SPI_H #include #include "mpconfigport.h" -// Routines common across chip families. +void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index); +uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad); uint8_t samd_peripherals_spi_baudrate_to_baud_reg_value(const uint32_t baudrate); uint32_t samd_peripherals_spi_baud_reg_value_to_baudrate(const uint8_t baud_reg_value); +bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad); Sercom* sercom_insts[SERCOM_INST_NUM]; -#ifdef SAMD21 -#include "samd21_peripherals.h" -#endif -#ifdef SAMD51 -#include "samd51_peripherals.h" -#endif - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_H +#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_SPI_H diff --git a/ports/atmel-samd/peripherals/timers.c b/ports/atmel-samd/peripherals/timers.c new file mode 100644 index 0000000000..cdcb92ac82 --- /dev/null +++ b/ports/atmel-samd/peripherals/timers.c @@ -0,0 +1,147 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "timers.h" + +#include "common-hal/pulseio/PulseOut.h" + +const uint16_t prescaler[8] = {1, 2, 4, 8, 16, 64, 256, 1024}; + +Tc* const tc_insts[TC_INST_NUM] = TC_INSTS; +Tcc* const tcc_insts[TCC_INST_NUM] = TCC_INSTS; + +IRQn_Type const tc_irq[TC_INST_NUM] = { +#ifdef TC0 + TC0_IRQn, +#endif +#ifdef TC1 + TC1_IRQn, +#endif +#ifdef TC2 + TC2_IRQn, +#endif +#ifdef TC3 + TC3_IRQn, +#endif +#ifdef TC4 + TC4_IRQn, +#endif +#ifdef TC5 + TC5_IRQn, +#endif +#ifdef TC6 + TC6_IRQn, +#endif +#ifdef TC7 + TC7_IRQn, +#endif +}; + +void tc_enable_interrupts(uint8_t tc_index) { + NVIC_DisableIRQ(tc_irq[tc_index]); + NVIC_ClearPendingIRQ(tc_irq[tc_index]); + NVIC_EnableIRQ(tc_irq[tc_index]); +} + +void tc_disable_interrupts(uint8_t tc_index) { + NVIC_DisableIRQ(tc_irq[tc_index]); + NVIC_ClearPendingIRQ(tc_irq[tc_index]); +} + +void tcc_set_enable(Tcc* tcc, bool enable) { + tcc->CTRLA.bit.ENABLE = enable; + while (tcc->SYNCBUSY.bit.ENABLE != 0) { + /* Wait for sync */ + } +} + +void tc_reset(Tc* tc) { + tc->COUNT16.CTRLA.bit.SWRST = 1; + while (tc->COUNT16.CTRLA.bit.SWRST == 1) { + } +} + +void shared_timer_handler(bool is_tc, uint8_t index) { + // Add calls to interrupt handlers for specific functionality here. + if (is_tc) { + pulseout_interrupt_handler(index); + } +} + +#ifdef SAMD51 +#define TC_OFFSET 0 +#endif +#ifdef SAMD21 +#define TC_OFFSET 3 +#endif + +void TCC0_Handler(void) { + shared_timer_handler(false, 0); +} +void TCC1_Handler(void) { + shared_timer_handler(false, 1); +} +void TCC2_Handler(void) { + shared_timer_handler(false, 2); +} +// TC0 - TC2 only exist on the SAMD51 +#ifdef TC0 +void TC0_Handler(void) { + shared_timer_handler(true, 0); +} +#endif +#ifdef TC1 +void TC1_Handler(void) { + shared_timer_handler(true, 1); +} +#endif +#ifdef TC2 +void TC2_Handler(void) { + shared_timer_handler(true, 2); +} +#endif +void TC3_Handler(void) { + shared_timer_handler(true, 3 - TC_OFFSET); +} +void TC4_Handler(void) { + shared_timer_handler(true, 4 - TC_OFFSET); +} +void TC5_Handler(void) { + shared_timer_handler(true, 5 - TC_OFFSET); +} +#ifdef TC6 +void TC6_Handler(void) { + shared_timer_handler(true, 6 - TC_OFFSET); +} +#endif +#ifdef TC7 +void TC7_Handler(void) { + shared_timer_handler(true, 7 - TC_OFFSET); +} +#endif diff --git a/ports/atmel-samd/timers.h b/ports/atmel-samd/peripherals/timers.h similarity index 100% rename from ports/atmel-samd/timers.h rename to ports/atmel-samd/peripherals/timers.h diff --git a/ports/atmel-samd/samd51_clocks.c b/ports/atmel-samd/samd51_clocks.c deleted file mode 100644 index cc3dd7917a..0000000000 --- a/ports/atmel-samd/samd51_clocks.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "clocks.h" - -#include "hpl_gclk_config.h" - -#include "shared-bindings/microcontroller/__init__.h" - -#include "py/runtime.h" - -bool gclk_enabled(uint8_t gclk) { - return GCLK->GENCTRL[gclk].bit.GENEN; -} - -void disable_gclk(uint8_t gclk) { - while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {} - GCLK->GENCTRL[gclk].bit.GENEN = false; - while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {} -} - -void connect_gclk_to_peripheral(uint8_t gclk, uint8_t peripheral) { - GCLK->PCHCTRL[peripheral].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclk); - while(GCLK->SYNCBUSY.reg != 0) {} -} - -void disconnect_gclk_from_peripheral(uint8_t gclk, uint8_t peripheral) { - GCLK->PCHCTRL[peripheral].reg = 0; -} - -void enable_clock_generator(uint8_t gclk, uint32_t source, uint16_t divisor) { - GCLK->GENCTRL[gclk].reg = GCLK_GENCTRL_SRC(source) | GCLK_GENCTRL_DIV(divisor) | GCLK_GENCTRL_GENEN; - while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {} -} - -void disable_clock_generator(uint8_t gclk) { - GCLK->GENCTRL[gclk].reg = 0; - while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {} -} - -bool clock_get_enabled(uint8_t type, uint8_t index) { - return false; -} - -bool clock_get_parent(uint8_t type, uint8_t index, uint8_t *p_type, uint8_t *p_index) { - return false; -} - -uint32_t clock_get_frequency(uint8_t type, uint8_t index) { - return 0; -} - -uint32_t clock_get_calibration(uint8_t type, uint8_t index) { - return 0; -} - -int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val) { - return -2; -} - -STATIC const mp_rom_map_elem_t samd_clock_global_dict_table[] = { -}; -MP_DEFINE_CONST_DICT(samd_clock_globals, samd_clock_global_dict_table); diff --git a/ports/atmel-samd/supervisor/filesystem.c b/ports/atmel-samd/supervisor/filesystem.c index 2ba29f279f..8a6010951f 100644 --- a/ports/atmel-samd/supervisor/filesystem.c +++ b/ports/atmel-samd/supervisor/filesystem.c @@ -32,13 +32,6 @@ #include "flash_api.h" -#ifdef EXPRESS_BOARD -// #include "common-hal/touchio/TouchIn.h" -#define INTERNAL_CIRCUITPY_CONFIG_START_ADDR (0x00040000 - 0x100 - CIRCUITPY_INTERNAL_NVM_SIZE) -#else -#define INTERNAL_CIRCUITPY_CONFIG_START_ADDR (0x00040000 - 0x010000 - 0x100 - CIRCUITPY_INTERNAL_NVM_SIZE) -#endif - fs_user_mount_t fs_user_mount_flash; mp_vfs_mount_t mp_vfs_mount_flash; diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index 8e6f2b1857..3e8d5bcc76 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -53,13 +53,16 @@ #include "common-hal/pulseio/PulseOut.h" #include "common-hal/pulseio/PWMOut.h" #include "common-hal/rtc/RTC.h" +#include "common-hal/touchio/TouchIn.h" #include "common-hal/usb_hid/Device.h" +#include "peripherals/cache.h" +#include "peripherals/clocks.h" +#include "peripherals/events.h" +#include "peripherals/external_interrupts.h" +#include "peripherals/dma.h" #include "shared-bindings/rtc/__init__.h" -#include "clocks.h" -#include "events.h" -#include "peripherals.h" -#include "shared_dma.h" #include "tick.h" +#include "usb.h" #ifdef CIRCUITPY_GAMEPAD_TICKS #include "shared-module/gamepad/__init__.h" @@ -180,22 +183,17 @@ safe_mode_t port_init(void) { #ifdef SAMD21 hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, 2); _pm_init(); +#endif clock_init(); -#endif -#ifdef SAMD51 - init_mcu(); -#endif + board_init(); // Configure millisecond timer initialization. tick_init(); - rtc_init(); - // Init the nvm controller. - // struct nvm_config config_nvm; - // nvm_get_config_defaults(&config_nvm); - // config_nvm.manual_page_write = false; - // nvm_set_config(&config_nvm); +#ifndef PIRKEY_M0 + rtc_init(); +#endif init_shared_dma(); #ifdef CIRCUITPY_CANARY_WORD @@ -205,9 +203,16 @@ safe_mode_t port_init(void) { } #endif - // if (PM->RCAUSE.bit.BOD33 == 1 || PM->RCAUSE.bit.BOD12 == 1) { - // return BROWNOUT; - // } + #ifdef SAMD21 + if (PM->RCAUSE.bit.BOD33 == 1 || PM->RCAUSE.bit.BOD12 == 1) { + return BROWNOUT; + } + #endif + #ifdef SAMD51 + if (RSTC->RCAUSE.bit.BODVDD == 1 || RSTC->RCAUSE.bit.BODCORE == 1) { + return BROWNOUT; + } + #endif if (board_requests_safe_mode()) { return USER_SAFE_MODE; @@ -240,38 +245,31 @@ void reset_port(void) { i2sout_reset(); #endif audio_dma_reset(); -// touchin_reset(); //pdmin_reset(); #endif - pulsein_reset(); +#ifdef SAMD21 + touchin_reset(); +#endif + eic_reset(); pulseout_reset(); pwmout_reset(); + +#ifndef PIRKEY_M0 + analogin_reset(); + analogout_reset(); rtc_reset(); +#endif reset_gclks(); - analogin_reset(); - #ifdef CIRCUITPY_GAMEPAD_TICKS gamepad_reset(); #endif - analogout_reset(); - reset_event_system(); reset_all_pins(); - // Set up debugging pins after reset_all_pins(). - - // Uncomment to init PIN_PA17 for debugging. - // struct port_config pin_conf; - // port_get_config_defaults(&pin_conf); - // - // pin_conf.direction = PORT_PIN_DIR_OUTPUT; - // port_pin_set_config(MICROPY_HW_LED1, &pin_conf); - // port_pin_set_output_level(MICROPY_HW_LED1, false); - // Output clocks for debugging. // not supported by SAMD51G; uncomment for SAMD51J or update for 51G // #ifdef SAMD51 @@ -283,52 +281,9 @@ void reset_port(void) { usb_hid_reset(); -// #ifdef CALIBRATE_CRYSTALLESS -// // If we are on USB lets double check our fine calibration for the clock and -// // save the new value if its different enough. -// if (mp_msc_enabled) { -// SYSCTRL->DFLLSYNC.bit.READREQ = 1; -// uint16_t saved_calibration = 0x1ff; -// if (strcmp((char*) INTERNAL_CIRCUITPY_CONFIG_START_ADDR, "CIRCUITPYTHON1") == 0) { -// saved_calibration = ((uint16_t *) INTERNAL_CIRCUITPY_CONFIG_START_ADDR)[8]; -// } -// while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { -// // TODO(tannewt): Run the mass storage stuff if this takes a while. -// } -// int16_t current_calibration = SYSCTRL->DFLLVAL.bit.FINE; -// if (abs(current_calibration - saved_calibration) > 10) { -// enum status_code error_code; -// uint8_t page_buffer[NVMCTRL_ROW_SIZE]; -// for (int i = 0; i < NVMCTRL_ROW_PAGES; i++) { -// do -// { -// error_code = nvm_read_buffer(INTERNAL_CIRCUITPY_CONFIG_START_ADDR + i * NVMCTRL_PAGE_SIZE, -// page_buffer + i * NVMCTRL_PAGE_SIZE, -// NVMCTRL_PAGE_SIZE); -// } while (error_code == STATUS_BUSY); -// } -// // If this is the first write, include the header. -// if (strcmp((char*) page_buffer, "CIRCUITPYTHON1") != 0) { -// memcpy(page_buffer, "CIRCUITPYTHON1", 15); -// } -// // First 16 bytes (0-15) are ID. Little endian! -// page_buffer[16] = current_calibration & 0xff; -// page_buffer[17] = current_calibration >> 8; -// do -// { -// error_code = nvm_erase_row(INTERNAL_CIRCUITPY_CONFIG_START_ADDR); -// } while (error_code == STATUS_BUSY); -// for (int i = 0; i < NVMCTRL_ROW_PAGES; i++) { -// do -// { -// error_code = nvm_write_buffer(INTERNAL_CIRCUITPY_CONFIG_START_ADDR + i * NVMCTRL_PAGE_SIZE, -// page_buffer + i * NVMCTRL_PAGE_SIZE, -// NVMCTRL_PAGE_SIZE); -// } while (error_code == STATUS_BUSY); -// } -// } -// } -// #endif + if (usb_connected()) { + save_usb_clock_calibration(); + } } /** diff --git a/ports/atmel-samd/tick.c b/ports/atmel-samd/tick.c index 27b5f05b44..6cd7c7833f 100644 --- a/ports/atmel-samd/tick.c +++ b/ports/atmel-samd/tick.c @@ -30,6 +30,7 @@ #include "supervisor/shared/autoreload.h" #include "shared-module/gamepad/__init__.h" +#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Processor.h" // Global millisecond tick count @@ -38,8 +39,13 @@ volatile uint64_t ticks_ms = 0; void SysTick_Handler(void) { // SysTick interrupt handler called when the SysTick timer reaches zero // (every millisecond). + common_hal_mcu_disable_interrupts(); ticks_ms += 1; + // Read the control register to reset the COUNTFLAG. + (void) SysTick->CTRL; + common_hal_mcu_enable_interrupts(); + #ifdef CIRCUITPY_AUTORELOAD_DELAY_MS autoreload_tick(); #endif @@ -61,7 +67,7 @@ void tick_delay(uint32_t us) { uint32_t us_until_next_tick = SysTick->VAL / ticks_per_us; uint32_t start_tick; while (us >= us_until_next_tick) { - start_tick=SysTick->VAL; // wait for SysTick->VAL to RESET + start_tick = SysTick->VAL; // wait for SysTick->VAL to RESET while (SysTick->VAL < start_tick) {} us -= us_until_next_tick; us_until_next_tick = 1000; @@ -72,11 +78,25 @@ void tick_delay(uint32_t us) { // us counts down! void current_tick(uint64_t* ms, uint32_t* us_until_ms) { uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000; - *ms = ticks_ms; - *us_until_ms = SysTick->VAL / ticks_per_us; + + // We disable interrupts to prevent ticks_ms from changing while we grab it. + common_hal_mcu_disable_interrupts(); + uint32_t tick_status = SysTick->CTRL; + uint32_t current_us = SysTick->VAL; + uint32_t tick_status2 = SysTick->CTRL; + uint64_t current_ms = ticks_ms; + // The second clause ensures our value actually rolled over. Its possible it hit zero between + // the VAL read and CTRL read. + if ((tick_status & SysTick_CTRL_COUNTFLAG_Msk) != 0 || + ((tick_status2 & SysTick_CTRL_COUNTFLAG_Msk) != 0 && current_us > ticks_per_us)) { + current_ms++; + } + common_hal_mcu_enable_interrupts(); + *ms = current_ms; + *us_until_ms = current_us / ticks_per_us; } void wait_until(uint64_t ms, uint32_t us_until_ms) { uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000; - while(ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {} + while (ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {} } diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 616e9875c1..907a4cbdfd 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -28,7 +28,7 @@ #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) -#define MICROPY_USE_INTERNAL_ERRNO (1) +#define MICROPY_USE_INTERNAL_ERRNO (0) #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_BUILTINS_COMPLEX (0) diff --git a/ports/nrf/common-hal/busio/I2C.c b/ports/nrf/common-hal/busio/I2C.c index 07b067a2cb..7e92a84ffe 100644 --- a/ports/nrf/common-hal/busio/I2C.c +++ b/ports/nrf/common-hal/busio/I2C.c @@ -32,7 +32,7 @@ #include "pins.h" #include "nrf.h" -void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t frequency) { +void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t frequency, uint32_t timeout ) { if (scl->pin == sda->pin) { mp_raise_ValueError("Invalid pins"); } diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index ac5741f771..62e9504307 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -82,7 +82,7 @@ #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) -#define MICROPY_USE_INTERNAL_ERRNO (1) +#define MICROPY_USE_INTERNAL_ERRNO (0) #define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_STR_CENTER (0) @@ -323,6 +323,7 @@ extern const struct _mp_obj_module_t ble_module; struct _music_data_t *music_data; \ const struct _pwm_events *pwm_active_events; \ const struct _pwm_events *pwm_pending_events; \ + mp_obj_t gamepad_singleton; \ #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) diff --git a/py/modbuiltins.c b/py/modbuiltins.c index 5e11b8d18c..cea87b1813 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -700,6 +700,7 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_IndentationError), MP_ROM_PTR(&mp_type_IndentationError) }, { MP_ROM_QSTR(MP_QSTR_IndexError), MP_ROM_PTR(&mp_type_IndexError) }, { MP_ROM_QSTR(MP_QSTR_KeyboardInterrupt), MP_ROM_PTR(&mp_type_KeyboardInterrupt) }, + { MP_ROM_QSTR(MP_QSTR_ReloadException), MP_ROM_PTR(&mp_type_ReloadException) }, { MP_ROM_QSTR(MP_QSTR_KeyError), MP_ROM_PTR(&mp_type_KeyError) }, { MP_ROM_QSTR(MP_QSTR_LookupError), MP_ROM_PTR(&mp_type_LookupError) }, { MP_ROM_QSTR(MP_QSTR_MemoryError), MP_ROM_PTR(&mp_type_MemoryError) }, diff --git a/py/moduerrno.c b/py/moduerrno.c index de66c941b0..660fca07a2 100644 --- a/py/moduerrno.c +++ b/py/moduerrno.c @@ -30,8 +30,6 @@ #include "py/obj.h" #include "py/mperrno.h" -#if MICROPY_PY_UERRNO - // This list can be defined per port in mpconfigport.h to tailor it to a // specific port's needs. If it's not defined then we provide a default. #ifndef MICROPY_PY_UERRNO_LIST @@ -61,6 +59,8 @@ #endif +#if MICROPY_PY_UERRNO + #if MICROPY_PY_UERRNO_ERRORCODE STATIC const mp_rom_map_elem_t errorcode_table[] = { #define X(e) { MP_ROM_INT(MP_ ## e), MP_ROM_QSTR(MP_QSTR_## e) }, @@ -100,6 +100,20 @@ const mp_obj_module_t mp_module_uerrno = { }; qstr mp_errno_to_str(mp_obj_t errno_val) { + // For commonly encountered errors, return human readable strings + if (MP_OBJ_IS_SMALL_INT(errno_val)) { + switch (MP_OBJ_SMALL_INT_VALUE(errno_val)) { + case EPERM: return MP_QSTR_Permission_space_denied; + case ENOENT: return MP_QSTR_No_space_such_space_file_slash_directory; + case EIO: return MP_QSTR_Input_slash_output_space_error; + case EACCES: return MP_QSTR_Permission_space_denied; + case EEXIST: return MP_QSTR_File_space_exists; + case ENODEV: return MP_QSTR_Unsupported_space_operation; + case EINVAL: return MP_QSTR_Invalid_space_argument; + } + } + + // Otherwise, return the Exxxx string for that error code #if MICROPY_PY_UERRNO_ERRORCODE // We have the errorcode dict so can do a lookup using the hash map mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&errorcode_dict.map, errno_val, MP_MAP_LOOKUP); @@ -119,4 +133,15 @@ qstr mp_errno_to_str(mp_obj_t errno_val) { #endif } +#else //MICROPY_PY_UERRNO + +qstr mp_errno_to_str(mp_obj_t errno_val) { + int v = MP_OBJ_SMALL_INT_VALUE(errno_val); + #define X(e) if (v == e) return (MP_QSTR_ ## e); + MICROPY_PY_UERRNO_LIST + #undef X + + return MP_QSTR_; +} + #endif //MICROPY_PY_UERRNO diff --git a/py/mperrno.h b/py/mperrno.h index caac116ab6..a028157ba7 100644 --- a/py/mperrno.h +++ b/py/mperrno.h @@ -142,12 +142,6 @@ #endif -#if MICROPY_PY_UERRNO - -#include "py/obj.h" - qstr mp_errno_to_str(mp_obj_t errno_val); -#endif - #endif // MICROPY_INCLUDED_PY_MPERRNO_H diff --git a/py/mpstate.h b/py/mpstate.h index 19a5d711ed..c509470662 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -136,6 +136,9 @@ typedef struct _mp_state_vm_t { mp_obj_exception_t mp_kbd_exception; #endif + // exception object of type ReloadException + mp_obj_exception_t mp_reload_exception; + // dictionary with loaded modules (may be exposed as sys.modules) mp_obj_dict_t mp_loaded_modules_dict; diff --git a/py/obj.h b/py/obj.h index e4d950b97c..d086d3c149 100644 --- a/py/obj.h +++ b/py/obj.h @@ -590,6 +590,7 @@ extern const mp_obj_type_t mp_type_ImportError; extern const mp_obj_type_t mp_type_IndentationError; extern const mp_obj_type_t mp_type_IndexError; extern const mp_obj_type_t mp_type_KeyboardInterrupt; +extern const mp_obj_type_t mp_type_ReloadException; extern const mp_obj_type_t mp_type_KeyError; extern const mp_obj_type_t mp_type_LookupError; extern const mp_obj_type_t mp_type_MemoryError; diff --git a/py/objexcept.c b/py/objexcept.c index 4844c7f92d..f0874df773 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -113,7 +113,6 @@ STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr mp_print_str(print, ""); return; } else if (o->args->len == 1) { - #if MICROPY_PY_UERRNO // try to provide a nice OSError error message if (o->base.type == &mp_type_OSError && MP_OBJ_IS_SMALL_INT(o->args->items[0])) { qstr qst = mp_errno_to_str(o->args->items[0]); @@ -122,7 +121,6 @@ STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr return; } } - #endif mp_obj_print_helper(print, o->args->items[0], PRINT_STR); return; } @@ -249,6 +247,7 @@ const mp_obj_type_t mp_type_ ## exc_name = { \ // http://docs.python.org/3/library/exceptions.html MP_DEFINE_EXCEPTION(SystemExit, BaseException) MP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException) +MP_DEFINE_EXCEPTION(ReloadException, BaseException) MP_DEFINE_EXCEPTION(GeneratorExit, BaseException) MP_DEFINE_EXCEPTION(Exception, BaseException) #if MICROPY_PY_ASYNC_AWAIT @@ -275,9 +274,7 @@ MP_DEFINE_EXCEPTION(Exception, BaseException) MP_DEFINE_EXCEPTION(UnboundLocalError, NameError) */ MP_DEFINE_EXCEPTION(OSError, Exception) -#if MICROPY_PY_BUILTINS_TIMEOUTERROR - MP_DEFINE_EXCEPTION(TimeoutError, OSError) -#endif + MP_DEFINE_EXCEPTION(TimeoutError, OSError) /* MP_DEFINE_EXCEPTION(BlockingIOError, OSError) MP_DEFINE_EXCEPTION(ChildProcessError, OSError) diff --git a/py/py.mk b/py/py.mk index 21f81c35d5..e934c3a83f 100644 --- a/py/py.mk +++ b/py/py.mk @@ -188,6 +188,7 @@ PY_O_BASENAME = \ objtype.o \ objzip.o \ opmethods.o \ + reload.o \ sequence.o \ stream.o \ binary.o \ diff --git a/py/reload.c b/py/reload.c new file mode 100644 index 0000000000..95305f2c9c --- /dev/null +++ b/py/reload.c @@ -0,0 +1,16 @@ +// +// Created by Roy Hooper on 2018-05-14. +// + +#include "reload.h" +#include "py/mpstate.h" + +void mp_raise_reload_exception(void) { + MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception)); +#if MICROPY_ENABLE_SCHEDULER + if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) { + MP_STATE_VM(sched_state) = MP_SCHED_PENDING; + } +#endif + +} diff --git a/py/reload.h b/py/reload.h new file mode 100644 index 0000000000..72e84e5ca6 --- /dev/null +++ b/py/reload.h @@ -0,0 +1,10 @@ +// +// Created by Roy Hooper on 2018-05-14. +// + +#ifndef CIRCUITPYTHON_RELOAD_H +#define CIRCUITPYTHON_RELOAD_H + +void mp_raise_reload_exception(void); + +#endif //CIRCUITPYTHON_RELOAD_H diff --git a/py/runtime.c b/py/runtime.c index cbec82f17c..a7ff57a47f 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -84,6 +84,12 @@ void mp_init(void) { MP_STATE_VM(mp_kbd_exception).args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj; #endif + MP_STATE_VM(mp_reload_exception).base.type = &mp_type_ReloadException; + MP_STATE_VM(mp_reload_exception).traceback_alloc = 0; + MP_STATE_VM(mp_reload_exception).traceback_len = 0; + MP_STATE_VM(mp_reload_exception).traceback_data = NULL; + MP_STATE_VM(mp_reload_exception).args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj; + // call port specific initialization if any #ifdef MICROPY_PORT_INIT_FUNC MICROPY_PORT_INIT_FUNC; diff --git a/shared-bindings/audioio/AudioOut.c b/shared-bindings/audioio/AudioOut.c index 3450b39712..36de117ac8 100644 --- a/shared-bindings/audioio/AudioOut.c +++ b/shared-bindings/audioio/AudioOut.c @@ -80,7 +80,8 @@ //| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE) //| speaker_enable.switch_to_output(value=True) //| -//| wav = audioio.WaveFile("cplay-5.1-16bit-16khz.wav") +//| data = open("cplay-5.1-16bit-16khz.wav", "rb") +//| wav = audioio.WaveFile(data) //| a = audioio.AudioOut(board.A0) //| //| print("playing") diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c index f8f60210e6..a5c000ae5a 100644 --- a/shared-bindings/bitbangio/I2C.c +++ b/shared-bindings/bitbangio/I2C.c @@ -35,6 +35,7 @@ #include "lib/utils/context_manager_helpers.h" #include "py/mperrno.h" #include "py/runtime.h" + //| .. currentmodule:: bitbangio //| //| :class:`I2C` --- Two wire serial protocol @@ -49,6 +50,7 @@ //| :param ~microcontroller.Pin scl: The clock pin //| :param ~microcontroller.Pin sda: The data pin //| :param int frequency: The clock frequency of the bus +//| :param int timeout: The maximum clock stretching timeout in microseconds //| STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); @@ -57,11 +59,12 @@ STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, self->base.type = &bitbangio_i2c_type; mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); - enum { ARG_scl, ARG_sda, ARG_frequency }; + enum { ARG_scl, ARG_sda, ARG_frequency, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 255} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -69,7 +72,7 @@ STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, assert_pin(args[ARG_sda].u_obj, false); const mcu_pin_obj_t* scl = MP_OBJ_TO_PTR(args[ARG_scl].u_obj); const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj); - shared_module_bitbangio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int); + shared_module_bitbangio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int, args[ARG_timeout].u_int); return (mp_obj_t)self; } diff --git a/shared-bindings/bitbangio/I2C.h b/shared-bindings/bitbangio/I2C.h index 9d393ee124..1ce4d21e91 100644 --- a/shared-bindings/bitbangio/I2C.h +++ b/shared-bindings/bitbangio/I2C.h @@ -39,7 +39,8 @@ extern const mp_obj_type_t bitbangio_i2c_type; extern void shared_module_bitbangio_i2c_construct(bitbangio_i2c_obj_t *self, const mcu_pin_obj_t * scl, const mcu_pin_obj_t * sda, - uint32_t frequency); + uint32_t frequency, + uint32_t us_timeout); extern void shared_module_bitbangio_i2c_deinit(bitbangio_i2c_obj_t *self); extern bool shared_module_bitbangio_i2c_deinited(bitbangio_i2c_obj_t *self); diff --git a/shared-bindings/board/__init__.h b/shared-bindings/board/__init__.h index 720239f280..2730e5f51b 100644 --- a/shared-bindings/board/__init__.h +++ b/shared-bindings/board/__init__.h @@ -29,6 +29,8 @@ #include "py/obj.h" +#include "shared-bindings/microcontroller/Pin.h" // for the pin definitions + extern const mp_obj_dict_t board_module_globals; #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BOARD___INIT___H diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c index b0954d6c8a..0d21d30f00 100644 --- a/shared-bindings/busio/I2C.c +++ b/shared-bindings/busio/I2C.c @@ -56,6 +56,7 @@ //| :param ~microcontroller.Pin scl: The clock pin //| :param ~microcontroller.Pin sda: The data pin //| :param int frequency: The clock frequency in Hertz +//| :param int timeout: The maximum clock stretching timeut - only for bitbang //| STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); @@ -63,11 +64,12 @@ STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz self->base.type = &busio_i2c_type; mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); - enum { ARG_scl, ARG_sda, ARG_frequency }; + enum { ARG_scl, ARG_sda, ARG_frequency, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 255} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -77,7 +79,7 @@ STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz assert_pin_free(scl); const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj); assert_pin_free(sda); - common_hal_busio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int); + common_hal_busio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int, args[ARG_timeout].u_int); return (mp_obj_t)self; } diff --git a/shared-bindings/busio/I2C.h b/shared-bindings/busio/I2C.h index 7185d6075c..739732e97b 100644 --- a/shared-bindings/busio/I2C.h +++ b/shared-bindings/busio/I2C.h @@ -46,7 +46,8 @@ extern const mp_obj_type_t busio_i2c_type; extern void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t * scl, const mcu_pin_obj_t * sda, - uint32_t frequency); + uint32_t frequency, + uint32_t timeout); extern void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self); extern bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self); diff --git a/shared-bindings/gamepad/GamePad.c b/shared-bindings/gamepad/GamePad.c index d80d1fcf65..1e95776d70 100644 --- a/shared-bindings/gamepad/GamePad.c +++ b/shared-bindings/gamepad/GamePad.c @@ -26,13 +26,15 @@ #include "py/obj.h" #include "py/runtime.h" #include "py/mphal.h" +#include "py/gc.h" +#include "py/mpstate.h" +#include "shared-module/gamepad/__init__.h" #include "shared-module/gamepad/GamePad.h" #include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/util.h" #include "GamePad.h" -gamepad_obj_t* gamepad_singleton = NULL; - //| .. currentmodule:: gamepad //| //| :class:`GamePad` -- Scan buttons for presses @@ -93,18 +95,24 @@ gamepad_obj_t* gamepad_singleton = NULL; //| STATIC mp_obj_t gamepad_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - if (!gamepad_singleton) { - gamepad_singleton = m_new_obj(gamepad_obj_t); - gamepad_singleton->base.type = &gamepad_type; + if (n_args > 8) { + mp_raise_TypeError("too many arguments"); } for (size_t i = 0; i < n_args; ++i) { if (!MP_OBJ_IS_TYPE(args[i], &digitalio_digitalinout_type)) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, - "Expected a %q", digitalio_digitalinout_type.name)); + mp_raise_TypeError("expected a DigitalInOut"); } + digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(args[i]); + raise_error_if_deinited( + common_hal_digitalio_digitalinout_deinited(pin)); + } + if (!MP_STATE_VM(gamepad_singleton)) { + gamepad_obj_t* gamepad_singleton = m_new_obj(gamepad_obj_t); + gamepad_singleton->base.type = &gamepad_type; + MP_STATE_VM(gamepad_singleton) = gc_make_long_lived(gamepad_singleton); } gamepad_init(n_args, args); - return MP_OBJ_FROM_PTR(gamepad_singleton); + return MP_OBJ_FROM_PTR(MP_STATE_VM(gamepad_singleton)); } @@ -119,9 +127,9 @@ STATIC mp_obj_t gamepad_make_new(const mp_obj_type_t *type, size_t n_args, //| held down) can be recorded for the next call. //| STATIC mp_obj_t gamepad_get_pressed(mp_obj_t self_in) { - gamepad_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_t gamepad = MP_OBJ_NEW_SMALL_INT(self->pressed); - self->pressed = 0; + gamepad_obj_t* gamepad_singleton = MP_STATE_VM(gamepad_singleton); + mp_obj_t gamepad = MP_OBJ_NEW_SMALL_INT(gamepad_singleton->pressed); + gamepad_singleton->pressed = 0; return gamepad; } MP_DEFINE_CONST_FUN_OBJ_1(gamepad_get_pressed_obj, gamepad_get_pressed); @@ -132,14 +140,12 @@ MP_DEFINE_CONST_FUN_OBJ_1(gamepad_get_pressed_obj, gamepad_get_pressed); //| Disable button scanning. //| STATIC mp_obj_t gamepad_deinit(mp_obj_t self_in) { - gamepad_singleton = NULL; + gamepad_reset(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(gamepad_deinit_obj, gamepad_deinit); -STATIC mp_obj_t gamepad_make_new(const mp_obj_type_t *type, size_t n_args, - size_t n_kw, const mp_obj_t *args); STATIC const mp_rom_map_elem_t gamepad_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_get_pressed), MP_ROM_PTR(&gamepad_get_pressed_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&gamepad_deinit_obj)}, diff --git a/shared-bindings/index.rst b/shared-bindings/index.rst index 76b5e340b8..d985878809 100644 --- a/shared-bindings/index.rst +++ b/shared-bindings/index.rst @@ -17,6 +17,9 @@ SAMD51, SAMD51 Express, and ESP8266. NOTE 2: **SAMD** and/or **SAMD Express** without additional numbers, means both SAMD21 & SAMD51 versions are supported. +NOTE 3: The `pIRkey SAMD21 board `_ is specialized and may not +have modules as listed below. + ================= ============================== Module Supported Ports ================= ============================== @@ -38,6 +41,7 @@ Module Supported Ports `os` **All Supported** `pulseio` **SAMD/SAMD Express** `random` **All Supported** +`rotaryio` **SAMD51, SAMD Express** `storage` **All Supported** `struct` **All Supported** `supervisor` **SAMD/SAMD Express** diff --git a/shared-bindings/rotaryio/IncrementalEncoder.c b/shared-bindings/rotaryio/IncrementalEncoder.c new file mode 100644 index 0000000000..65d4ba98bd --- /dev/null +++ b/shared-bindings/rotaryio/IncrementalEncoder.c @@ -0,0 +1,168 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "lib/utils/context_manager_helpers.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "py/runtime0.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/rotaryio/IncrementalEncoder.h" +#include "shared-bindings/util.h" + +//| .. currentmodule:: rotaryio +//| +//| :class:`IncrementalEncoder` -- Track the relative position of an incremental encoder +//| ==================================================================================== +//| +//| IncrementalEncoder determines the relative rotational position based on two series of pulses. +//| +//| .. class:: IncrementalEncoder(pin_a, pin_b) +//| +//| Create an IncrementalEncoder object associated with the given pins. It tracks the positional +//| state of an incremental rotary encoder (also known as a quadrature encoder.) Position is +//| relative to the position when the object is contructed. +//| +//| :param ~microcontroller.Pin pin_a: First pin to read pulses from. +//| :param ~microcontroller.Pin pin_b: Second pin to read pulses from. +//| +//| For example:: +//| +//| import rotaryio +//| import time +//| from board import * +//| +//| enc = rotaryio.IncrementalEncoder(D1, D2) +//| last_position = None +//| while True: +//| position = enc.position +//| if last_position == None or position != last_position: +//| print(position) +//| last_position = position +//| +STATIC mp_obj_t rotaryio_incrementalencoder_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 2, 2, true); + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + enum { ARG_pin_a, ARG_pin_b }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pin_a, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_pin_b, MP_ARG_REQUIRED | MP_ARG_OBJ }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + assert_pin(args[ARG_pin_a].u_obj, false); + const mcu_pin_obj_t* pin_a = MP_OBJ_TO_PTR(args[ARG_pin_a].u_obj); + assert_pin_free(pin_a); + + assert_pin(args[ARG_pin_b].u_obj, false); + const mcu_pin_obj_t* pin_b = MP_OBJ_TO_PTR(args[ARG_pin_b].u_obj); + assert_pin_free(pin_b); + + rotaryio_incrementalencoder_obj_t *self = m_new_obj(rotaryio_incrementalencoder_obj_t); + self->base.type = &rotaryio_incrementalencoder_type; + + common_hal_rotaryio_incrementalencoder_construct(self, pin_a, pin_b); + + return MP_OBJ_FROM_PTR(self); +} + +//| .. method:: deinit() +//| +//| Deinitializes the IncrementalEncoder and releases any hardware resources for reuse. +//| +STATIC mp_obj_t rotaryio_incrementalencoder_deinit(mp_obj_t self_in) { + rotaryio_incrementalencoder_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_rotaryio_incrementalencoder_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(rotaryio_incrementalencoder_deinit_obj, rotaryio_incrementalencoder_deinit); + +//| .. method:: __enter__() +//| +//| No-op used by Context Managers. +//| +// Provided by context manager helper. + +//| .. method:: __exit__() +//| +//| Automatically deinitializes the hardware when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info. +//| +STATIC mp_obj_t rotaryio_incrementalencoder_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_rotaryio_incrementalencoder_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rotaryio_incrementalencoder___exit___obj, 4, 4, rotaryio_incrementalencoder_obj___exit__); + + +//| .. attribute:: position +//| +//| The current position in terms of pulses. The number of pulses per rotation is defined by the +//| specific hardware. +//| +STATIC mp_obj_t rotaryio_incrementalencoder_obj_get_position(mp_obj_t self_in) { + rotaryio_incrementalencoder_obj_t *self = MP_OBJ_TO_PTR(self_in); + raise_error_if_deinited(common_hal_rotaryio_incrementalencoder_deinited(self)); + + return mp_obj_new_int(common_hal_rotaryio_incrementalencoder_get_position(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(rotaryio_incrementalencoder_get_position_obj, rotaryio_incrementalencoder_obj_get_position); + +STATIC mp_obj_t rotaryio_incrementalencoder_obj_set_position(mp_obj_t self_in, mp_obj_t new_position) { + rotaryio_incrementalencoder_obj_t *self = MP_OBJ_TO_PTR(self_in); + raise_error_if_deinited(common_hal_rotaryio_incrementalencoder_deinited(self)); + + common_hal_rotaryio_incrementalencoder_set_position(self, mp_obj_get_int(new_position)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(rotaryio_incrementalencoder_set_position_obj, rotaryio_incrementalencoder_obj_set_position); + +const mp_obj_property_t rotaryio_incrementalencoder_position_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&rotaryio_incrementalencoder_get_position_obj, + (mp_obj_t)&rotaryio_incrementalencoder_set_position_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t rotaryio_incrementalencoder_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&rotaryio_incrementalencoder_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&rotaryio_incrementalencoder___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_position), MP_ROM_PTR(&rotaryio_incrementalencoder_position_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(rotaryio_incrementalencoder_locals_dict, rotaryio_incrementalencoder_locals_dict_table); + +const mp_obj_type_t rotaryio_incrementalencoder_type = { + { &mp_type_type }, + .name = MP_QSTR_IncrementalEncoder, + .make_new = rotaryio_incrementalencoder_make_new, + .locals_dict = (mp_obj_dict_t*)&rotaryio_incrementalencoder_locals_dict, +}; diff --git a/shared-bindings/rotaryio/IncrementalEncoder.h b/shared-bindings/rotaryio/IncrementalEncoder.h new file mode 100644 index 0000000000..f70632aefb --- /dev/null +++ b/shared-bindings/rotaryio/IncrementalEncoder.h @@ -0,0 +1,43 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_ROTARYIO_INCREMENTALENCODER_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_ROTARYIO_INCREMENTALENCODER_H + +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/rotaryio/IncrementalEncoder.h" + +extern const mp_obj_type_t rotaryio_incrementalencoder_type; + +extern void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t* self, + const mcu_pin_obj_t* pin_a, const mcu_pin_obj_t* pin_b); +extern void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_obj_t* self); +extern bool common_hal_rotaryio_incrementalencoder_deinited(rotaryio_incrementalencoder_obj_t* self); +extern mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t* self); +extern void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t* self, + mp_int_t new_position); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ROTARYIO_INCREMENTALENCODER_H diff --git a/shared-bindings/rotaryio/__init__.c b/shared-bindings/rotaryio/__init__.c new file mode 100644 index 0000000000..a0166771ab --- /dev/null +++ b/shared-bindings/rotaryio/__init__.c @@ -0,0 +1,75 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/rotaryio/__init__.h" +#include "shared-bindings/rotaryio/IncrementalEncoder.h" + +//| :mod:`rotaryio` --- Support for reading rotation sensors +//| ======================================================== +//| +//| .. module:: rotaryio +//| :synopsis: Support for reading rotation sensors +//| :platform: SAMD +//| +//| The `rotaryio` module contains classes to read different rotation encoding schemes. See +//| `Wikipedia's Rotary Encoder page `_ for more +//| background. +//| +//| Libraries +//| +//| .. toctree:: +//| :maxdepth: 3 +//| +//| IncrementalEncoder +//| + +//| .. warning:: This module is not available in some SAMD21 (aka M0) builds. See the +//| :ref:`module-support-matrix` for more info. +//| + +//| All classes change hardware state and should be deinitialized when they +//| are no longer needed if the program continues after use. To do so, either +//| call :py:meth:`!deinit` or use a context manager. See +//| :ref:`lifetime-and-contextmanagers` for more info. +//| + +STATIC const mp_rom_map_elem_t rotaryio_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rotaryio) }, + { MP_ROM_QSTR(MP_QSTR_IncrementalEncoder), MP_ROM_PTR(&rotaryio_incrementalencoder_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(rotaryio_module_globals, rotaryio_module_globals_table); + +const mp_obj_module_t rotaryio_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&rotaryio_module_globals, +}; diff --git a/shared-bindings/rotaryio/__init__.h b/shared-bindings/rotaryio/__init__.h new file mode 100644 index 0000000000..5d051d5a1a --- /dev/null +++ b/shared-bindings/rotaryio/__init__.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft + * + * 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. + */ + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_ROTARYIO___INIT___H +#define MICROPY_INCLUDED_SHARED_BINDINGS_ROTARYIO___INIT___H + +#include "py/obj.h" + +// Nothing now. + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ROTARYIO___INIT___H diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c index a82459ad78..e6429be320 100644 --- a/shared-bindings/supervisor/__init__.c +++ b/shared-bindings/supervisor/__init__.c @@ -25,11 +25,16 @@ */ #include "py/obj.h" #include "py/runtime.h" + #include "py/reload.h" + + #include "lib/utils/interrupt_char.h" #include "supervisor/shared/autoreload.h" + #include "supervisor/shared/rgb_led_status.h" #include "shared-bindings/supervisor/__init__.h" #include "shared-bindings/supervisor/Runtime.h" + //| :mod:`supervisor` --- Supervisor settings //| ================================================= //| @@ -91,12 +96,25 @@ STATIC mp_obj_t supervisor_set_rgb_status_brightness(mp_obj_t lvl){ } MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_rgb_status_brightness_obj, supervisor_set_rgb_status_brightness); +//| .. method:: reload() +//| +//| Reload the main Python code and run it (equivalent to hitting Ctrl-D at the REPL). +//| +STATIC mp_obj_t supervisor_reload(void) { + reload_requested = true; + mp_raise_reload_exception(); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_0(supervisor_reload_obj, supervisor_reload); + + STATIC const mp_rom_map_elem_t supervisor_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_supervisor) }, { MP_OBJ_NEW_QSTR(MP_QSTR_enable_autoreload), MP_ROM_PTR(&supervisor_enable_autoreload_obj) }, { MP_OBJ_NEW_QSTR(MP_QSTR_disable_autoreload), MP_ROM_PTR(&supervisor_disable_autoreload_obj) }, { MP_OBJ_NEW_QSTR(MP_QSTR_set_rgb_status_brightness), MP_ROM_PTR(&supervisor_set_rgb_status_brightness_obj) }, { MP_ROM_QSTR(MP_QSTR_runtime), MP_ROM_PTR(&common_hal_supervisor_runtime_obj) }, + { MP_ROM_QSTR(MP_QSTR_reload), MP_ROM_PTR(&supervisor_reload_obj) }, }; STATIC MP_DEFINE_CONST_DICT(supervisor_module_globals, supervisor_module_globals_table); diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c index b4137706ee..a105941c09 100644 --- a/shared-bindings/time/__init__.c +++ b/shared-bindings/time/__init__.c @@ -34,6 +34,8 @@ #include "shared-bindings/rtc/__init__.h" #include "shared-bindings/time/__init__.h" +#define EPOCH1970_EPOCH2000_DIFF_SECS 946684800 + //| :mod:`time` --- time and timing related functions //| ======================================================== //| @@ -183,13 +185,14 @@ void struct_time_to_tm(mp_obj_t t, timeutils_struct_time_t *tm) { // elems[8] tm_isdst is not supported } +#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE mp_obj_t MP_WEAK rtc_get_time_source_time(void) { mp_raise_RuntimeError("RTC is not supported on this board"); } //| .. method:: time() //| -//| Return the current time in seconds since since Jan 1, 2000. +//| Return the current time in seconds since since Jan 1, 1970. //| //| :return: the current time //| :rtype: int @@ -197,17 +200,18 @@ mp_obj_t MP_WEAK rtc_get_time_source_time(void) { STATIC mp_obj_t time_time(void) { timeutils_struct_time_t tm; struct_time_to_tm(rtc_get_time_source_time(), &tm); - mp_uint_t secs = timeutils_seconds_since_2000(tm.tm_year, tm.tm_mon, tm.tm_mday, // mp_uint_t date + mp_uint_t secs = timeutils_seconds_since_2000(tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); - return mp_obj_new_int_from_uint(secs); + return mp_obj_new_int_from_uint(secs + EPOCH1970_EPOCH2000_DIFF_SECS); } MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); //| .. method:: localtime([secs]) //| -//| Convert a time expressed in seconds since Jan 1, 2000 to a struct_time in +//| Convert a time expressed in seconds since Jan 1, 1970 to a struct_time in //| local time. If secs is not provided or None, the current time as returned //| by time() is used. +//| The earliest date for which it can generate a time is Jan 1, 2000. //| //| :return: the current time //| :rtype: time.struct_time @@ -217,8 +221,12 @@ STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { return rtc_get_time_source_time(); } + mp_int_t secs = mp_obj_int_get_checked(args[0]); + if (secs < EPOCH1970_EPOCH2000_DIFF_SECS) + mp_raise_msg(&mp_type_OverflowError, "timestamp out of range for platform time_t"); + timeutils_struct_time_t tm; - timeutils_seconds_since_2000_to_struct_time(mp_obj_get_int(args[0]), &tm); + timeutils_seconds_since_2000_to_struct_time(secs - EPOCH1970_EPOCH2000_DIFF_SECS, &tm); return struct_time_from_tm(&tm); } @@ -247,11 +255,16 @@ STATIC mp_obj_t time_mktime(mp_obj_t t) { mp_raise_TypeError("function takes exactly 9 arguments"); } - return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), - mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5]))); + if (mp_obj_get_int(elem[0]) < 2000) + mp_raise_msg(&mp_type_OverflowError, "timestamp out of range for platform time_t"); + + mp_uint_t secs = timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), + mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5])); + return mp_obj_new_int_from_uint(secs + EPOCH1970_EPOCH2000_DIFF_SECS); } MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime); -#endif +#endif // MICROPY_LONGINT_IMPL +#endif // MICROPY_PY_COLLECTIONS STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_time) }, @@ -260,10 +273,14 @@ STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&time_sleep_obj) }, #if MICROPY_PY_COLLECTIONS { MP_ROM_QSTR(MP_QSTR_struct_time), MP_ROM_PTR(&struct_time_type_obj) }, + #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) }, { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) }, - #endif + #endif // MICROPY_LONGINT_IMPL + #endif // MICROPY_PY_COLLECTIONS + #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); diff --git a/shared-module/bitbangio/I2C.c b/shared-module/bitbangio/I2C.c index 7eeda0e00e..47529748a5 100644 --- a/shared-module/bitbangio/I2C.c +++ b/shared-module/bitbangio/I2C.c @@ -25,16 +25,15 @@ */ #include "shared-bindings/bitbangio/I2C.h" - #include "py/mperrno.h" #include "py/obj.h" +#include "py/runtime.h" #include "common-hal/microcontroller/Pin.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-module/bitbangio/types.h" -#define I2C_STRETCH_LIMIT 255 STATIC void delay(bitbangio_i2c_obj_t *self) { // We need to use an accurate delay to get acceptable I2C @@ -48,11 +47,16 @@ STATIC void scl_low(bitbangio_i2c_obj_t *self) { STATIC void scl_release(bitbangio_i2c_obj_t *self) { common_hal_digitalio_digitalinout_set_value(&self->scl, true); + uint32_t count = self->us_timeout; delay(self); // For clock stretching, wait for the SCL pin to be released, with timeout. - for (int count = I2C_STRETCH_LIMIT; !common_hal_digitalio_digitalinout_get_value(&self->scl) && count; --count) { + for (; !common_hal_digitalio_digitalinout_get_value(&self->scl) && count; --count) { common_hal_mcu_delay_us(1); } + // raise exception on timeout + if (count == 0) { + mp_raise_msg(&mp_type_TimeoutError, "Clock stretch too long"); + } } STATIC void sda_low(bitbangio_i2c_obj_t *self) { @@ -142,7 +146,10 @@ STATIC bool read_byte(bitbangio_i2c_obj_t *self, uint8_t *val, bool ack) { void shared_module_bitbangio_i2c_construct(bitbangio_i2c_obj_t *self, const mcu_pin_obj_t * scl, const mcu_pin_obj_t * sda, - uint32_t frequency) { + uint32_t frequency, + uint32_t us_timeout) { + + self->us_timeout = us_timeout; self->us_delay = 500000 / frequency; if (self->us_delay == 0) { self->us_delay = 1; diff --git a/shared-module/bitbangio/types.h b/shared-module/bitbangio/types.h index dfe50f0499..6d17234741 100644 --- a/shared-module/bitbangio/types.h +++ b/shared-module/bitbangio/types.h @@ -36,6 +36,7 @@ typedef struct { digitalio_digitalinout_obj_t scl; digitalio_digitalinout_obj_t sda; uint32_t us_delay; + uint32_t us_timeout; volatile bool locked; } bitbangio_i2c_obj_t; diff --git a/shared-module/busio/I2C.c b/shared-module/busio/I2C.c index 68d6ea22ab..06e1af10a1 100644 --- a/shared-module/busio/I2C.c +++ b/shared-module/busio/I2C.c @@ -30,8 +30,8 @@ #include "py/nlr.h" void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, - const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t freq) { - shared_module_bitbangio_i2c_construct(&self->bitbang, scl, sda, freq); + const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t freq, uint32_t timeout) { + shared_module_bitbangio_i2c_construct(&self->bitbang, scl, sda, freq, timeout); } bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) { diff --git a/shared-module/gamepad/GamePad.c b/shared-module/gamepad/GamePad.c index cd1df9b574..2c14fa02a4 100644 --- a/shared-module/gamepad/GamePad.c +++ b/shared-module/gamepad/GamePad.c @@ -26,6 +26,7 @@ #include +#include "py/mpstate.h" #include "__init__.h" #include "GamePad.h" @@ -35,17 +36,24 @@ void gamepad_init(size_t n_pins, const mp_obj_t* pins) { - for (size_t i=0; i<8; ++i) { + gamepad_obj_t* gamepad_singleton = MP_STATE_VM(gamepad_singleton); + for (size_t i = 0; i < 8; ++i) { gamepad_singleton->pins[i] = NULL; } - for (size_t i=0; ipulls = 0; + for (size_t i = 0; i < n_pins; ++i) { digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(pins[i]); - raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(pin)); digitalio_direction_t direction = common_hal_digitalio_digitalinout_get_direction(pin); - digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(pin); - if (direction != DIRECTION_INPUT || pull == PULL_NONE) { + if (direction != DIRECTION_INPUT) { common_hal_digitalio_digitalinout_switch_to_input(pin, PULL_UP); } + digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(pin); + if (pull == PULL_NONE) { + common_hal_digitalio_digitalinout_set_pull(pin, PULL_UP); + } + if (pull != PULL_DOWN) { + gamepad_singleton->pulls |= 1 << i; + } gamepad_singleton->pins[i] = pin; } gamepad_singleton->last = 0; diff --git a/shared-module/gamepad/GamePad.h b/shared-module/gamepad/GamePad.h index e5f709134d..9fd5c9626e 100644 --- a/shared-module/gamepad/GamePad.h +++ b/shared-module/gamepad/GamePad.h @@ -36,10 +36,9 @@ typedef struct { digitalio_digitalinout_obj_t* pins[8]; volatile uint8_t last; volatile uint8_t pressed; + uint8_t pulls; } gamepad_obj_t; -extern gamepad_obj_t* gamepad_singleton; - void gamepad_init(size_t n_pins, const mp_obj_t* pins); #endif // MICROPY_INCLUDED_GAMEPAD_GAMEPAD_H diff --git a/shared-module/gamepad/__init__.c b/shared-module/gamepad/__init__.c index 591a2fa0a0..8414ddfbea 100644 --- a/shared-module/gamepad/__init__.c +++ b/shared-module/gamepad/__init__.c @@ -26,6 +26,7 @@ #include +#include "py/mpstate.h" #include "__init__.h" #include "GamePad.h" @@ -33,25 +34,27 @@ void gamepad_tick(void) { + gamepad_obj_t* gamepad_singleton = MP_STATE_VM(gamepad_singleton); if (!gamepad_singleton) { return; } uint8_t gamepad_current = 0; - for (int i=0; i<8; ++i) { + uint8_t bit = 1; + for (int i = 0; i < 8; ++i) { digitalio_digitalinout_obj_t* pin = gamepad_singleton->pins[i]; if (!pin) { break; } - digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(pin); - bool value = common_hal_digitalio_digitalinout_get_value(pin); - if ((pull == PULL_UP && !value) || (pull == PULL_DOWN && value)) { - gamepad_current |= 1 << i; + if (common_hal_digitalio_digitalinout_get_value(pin)) { + gamepad_current |= bit; } + bit <<= 1; } + gamepad_current ^= gamepad_singleton->pulls; gamepad_singleton->pressed |= gamepad_singleton->last & gamepad_current; gamepad_singleton->last = gamepad_current; } void gamepad_reset(void) { - gamepad_singleton = NULL; + MP_STATE_VM(gamepad_singleton) = NULL; } diff --git a/supervisor/shared/autoreload.c b/supervisor/shared/autoreload.c index 39c33c05ea..2a7fd1e9d8 100644 --- a/supervisor/shared/autoreload.c +++ b/supervisor/shared/autoreload.c @@ -26,29 +26,29 @@ #include "autoreload.h" -#include "lib/utils/interrupt_char.h" #include "py/mphal.h" +#include "py/reload.h" volatile uint32_t autoreload_delay_ms = 0; bool autoreload_enabled = false; static bool autoreload_suspended = false; -volatile bool reload_next_character = false; +volatile bool reload_requested = false; inline void autoreload_tick() { if (autoreload_delay_ms == 0) { return; } if (autoreload_delay_ms == 1 && autoreload_enabled && - !autoreload_suspended && !reload_next_character) { - mp_keyboard_interrupt(); - reload_next_character = true; + !autoreload_suspended && !reload_requested) { + mp_raise_reload_exception(); + reload_requested = true; } autoreload_delay_ms--; } void autoreload_enable() { autoreload_enabled = true; - reload_next_character = false; + reload_requested = false; } void autoreload_disable() { @@ -73,5 +73,5 @@ void autoreload_start() { void autoreload_stop() { autoreload_delay_ms = 0; - reload_next_character = false; + reload_requested = false; } diff --git a/supervisor/shared/autoreload.h b/supervisor/shared/autoreload.h index 62f9fe0738..bcb1001513 100644 --- a/supervisor/shared/autoreload.h +++ b/supervisor/shared/autoreload.h @@ -29,7 +29,7 @@ #include -extern volatile bool reload_next_character; +extern volatile bool reload_requested; void autoreload_tick(void); diff --git a/supervisor/shared/rgb_led_status.c b/supervisor/shared/rgb_led_status.c index 8f1b506fea..584d021b0e 100644 --- a/supervisor/shared/rgb_led_status.c +++ b/supervisor/shared/rgb_led_status.c @@ -27,7 +27,6 @@ #include "mphalport.h" #include "common-hal/microcontroller/Pin.h" #include "rgb_led_status.h" -#include "pins.h" #ifdef MICROPY_HW_NEOPIXEL uint8_t rgb_status_brightness = 63; diff --git a/tests/basics/errno1.py b/tests/basics/errno1.py index 63930b767f..bbbfac10ca 100644 --- a/tests/basics/errno1.py +++ b/tests/basics/errno1.py @@ -11,7 +11,10 @@ print(type(uerrno.EIO)) # check that errors are rendered in a nice way msg = str(OSError(uerrno.EIO)) -print(msg[:7], msg[-5:]) +print(msg[:7], msg[msg.find(']'):]) + +msg = str(OSError(uerrno.ENOBUFS)) +print(msg[:7], msg[msg.find(']'):]) # check that unknown errno is still rendered print(str(OSError(9999))) diff --git a/tests/basics/errno1.py.exp b/tests/basics/errno1.py.exp index c3703df4a2..b5dd529e46 100644 --- a/tests/basics/errno1.py.exp +++ b/tests/basics/errno1.py.exp @@ -1,3 +1,4 @@ -[Errno ] EIO +[Errno ] Input/output error +[Errno ] ENOBUFS 9999 diff --git a/tests/pyboard.py b/tests/pyboard.py index 3a82f6a6a3..616773a313 120000 --- a/tests/pyboard.py +++ b/tests/pyboard.py @@ -1 +1 @@ -../tools/pyboard.py \ No newline at end of file +../tools/cpboard.py \ No newline at end of file diff --git a/tools/build_adafruit_bins.sh b/tools/build_adafruit_bins.sh index 004877f8ee..6ad0858272 100755 --- a/tools/build_adafruit_bins.sh +++ b/tools/build_adafruit_bins.sh @@ -2,7 +2,7 @@ rm -rf ports/atmel-samd/build* rm -rf ports/esp8266/build* rm -rf ports/nrf/build* -ATMEL_BOARDS="arduino_zero circuitplayground_express feather_m0_basic feather_m0_adalogger itsybitsy_m0_express itsybitsy_m4_express feather_m0_rfm69 feather_m0_rfm9x feather_m0_express feather_m4_express metro_m0_express metro_m4_express pirkey_m0 trinket_m0 gemma_m0 feather52" +ATMEL_BOARDS="arduino_zero circuitplayground_express circuitplayground_express_crickit feather_m0_basic feather_m0_adalogger itsybitsy_m0_express itsybitsy_m4_express feather_m0_rfm69 feather_m0_rfm9x feather_m0_express feather_m0_express_crickit feather_m4_express metro_m0_express metro_m4_express pirkey_m0 trinket_m0 gemma_m0 feather52" ROSIE_SETUPS="rosie-ci" PARALLEL="-j 5" diff --git a/tools/cpboard.py b/tools/cpboard.py new file mode 100644 index 0000000000..0b9c43c614 --- /dev/null +++ b/tools/cpboard.py @@ -0,0 +1,684 @@ +#!/usr/bin/env python3 +# +# This file is part of the MicroPython project, http://micropython.org/ +# +# The MIT License (MIT) +# +# Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +# Copyright (c) 2018 Noralf Trønnes +# +# Parts taken from pyboard.py: +# Copyright (c) 2014-2016 Damien P. George +# Copyright (c) 2017 Paul Sokolovsky +# +# 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. + +import os +import re +import serial +import sys +import time + +import serial.tools.list_ports +import sh +import shutil + +class CPboardError(BaseException): + pass + +# supervisor/messages/default.h: +MSG_NEWLINE = b"\r\n" +MSG_SAFE_MODE_CRASH = b"Looks like our core CircuitPython code crashed hard. Whoops!" +MSG_SAFE_MODE_BROWN_OUT_LINE_1 = b"The microcontroller's power dipped. Please make sure your power supply provides" +MSG_SAFE_MODE_BROWN_OUT_LINE_2 = b"enough power for the whole circuit and press reset (after ejecting CIRCUITPY)." +MSG_WAIT_BEFORE_REPL = b"Press any key to enter the REPL. Use CTRL-D to reload." + +class REPL: + CHAR_CTRL_A = b'\x01' + CHAR_CTRL_B = b'\x02' + CHAR_CTRL_C = b'\x03' + CHAR_CTRL_D = b'\x04' + + def __init__(self, board): + self.board = board + self.write_chunk_size = 32 + self.safe_mode = False + self.session = b'' + + def __enter__(self): + self.reset() + return self + + def __exit__(self, exception_type, exception_value, traceback): + pass + + @property + def serial(self): + return self.board.serial + + def read(self): + if self.serial.inWaiting(): + data = self.serial.read(self.serial.inWaiting()) + else: + data = b'' + self.session += data + return data + + def read_until(self, ending, timeout=10): + data = b'' + timeout_count = 0 + while True: + if data.endswith(ending): + break + elif self.serial.inWaiting() > 0: + new_data = self.serial.read(1) + data += new_data + self.session += new_data + timeout_count = 0 + else: + timeout_count += 1 + if timeout is not None and timeout_count >= 100 * timeout: + raise TimeoutError(110, "timeout waiting for", ending) + time.sleep(0.01) + return data + + def write(self, data, chunk_size=None): + if chunk_size is None: + chunk_size = self.write_chunk_size + if not isinstance(data, bytes): + data = bytes(data, encoding='utf8') + + for i in range(0, len(data), chunk_size): + chunk = data[i:min(i + chunk_size, len(data))] + self.session += chunk + self.serial.write(chunk) + time.sleep(0.01) + + def reset(self): + # Use read() since serial.reset_input_buffer() fails with termios.error now and then + self.read() + self.session = b'' + self.write(b'\r' + REPL.CHAR_CTRL_C + REPL.CHAR_CTRL_C) # interrupt any running program + self.write(b'\r' + REPL.CHAR_CTRL_B) # enter or reset friendly repl + data = self.read_until(b'>>> ') + + def execute(self, code, timeout=10, async=False): + self.read() # Throw away + + self.write(REPL.CHAR_CTRL_A) + self.read_until(b'\r\n>') + + self.write(code) + + self.write(REPL.CHAR_CTRL_D) + if async: + return b'', b'' + self.read_until(b'OK') + + output = self.read_until(b'\x04', timeout=timeout) + output = output[:-1] + + error = self.read_until(b'\x04') + error = error[:-1] + + return output, error + + def run(self): + if self.safe_mode: + raise RuntimeError("Can't run in safe mode") + + self.reset() + + self.write(REPL.CHAR_CTRL_D) + data = self.read_until(b' output:\r\n') + if b'Running in safe mode' in data: + self.safe_mode = True + raise RuntimeError("Can't run in safe mode") + + # TODO: MSG_SAFE_MODE_CRASH + # TODO: BROWNOUT + + marker = MSG_NEWLINE + MSG_WAIT_BEFORE_REPL + MSG_NEWLINE + data = self.read_until(marker) + data = data.split(marker)[0] + + # Haven't found out why we have to strip off this... + if data.endswith(b'\r\n\r\n'): + data = data[:-4] + return data + + +class Disk: + def __init__(self, dev): + self.dev = os.path.realpath(dev) + self.mountpoint = None + with open('/etc/mtab', 'r') as f: + mtab = f.read() + mount = [mount.split(' ') for mount in mtab.splitlines() if mount.startswith(self.dev)] + if mount: + self._path = mount[0][1] + else: + name = os.path.basename(dev) + sh.pmount("-tvfat", dev, name, _timeout=10) + self.mountpoint = "/media/" + name + self._path = self.mountpoint + + def __enter__(self): + return self + + def __exit__(self, exception_type, exception_value, traceback): + try: + self.close() + except: + pass + + @property + def path(self): + return self._path + + def close(self): + if not self.mountpoint: + return + mountpoint = self.mountpoint + self.mountpoint = None + + start_time = time.monotonic() + unmounted = False + while not unmounted and start_time - time.monotonic() < 30: + try: + sh.pumount(mountpoint) + unmounted = True + except sh.ErrorReturnCode_5: + time.sleep(0.1) + + def sync(self): + disk_device = os.path.basename(self.dev)[:-1] + os.sync() + # Monitor the block device so we know when the sync request is actually finished. + with open("/sys/block/" + disk_device + "/stat", "r") as f: + disk_inflight = 1 + last_wait_time = 0 + wait_time = 1 + while disk_inflight > 0 or wait_time > last_wait_time: + f.seek(0) + stats = f.read() + block_stats = stats.split() + disk_inflight = int(block_stats[8]) + last_wait_time = wait_time + wait_time = int(block_stats[9]) + + def copy(self, src, dst=None, sync=True): + if dst is None: + dst = os.path.basename(src) + shutil.copy(src, os.path.join(self.path, dst)) + if sync: + self.sync() + + +class Firmware: + def __init__(self, board): + self.board = board + + @property + def disk(self): + disks = self.board.get_disks() + if len(disks) != 1: + raise RuntimeError("Boot disk not found for: " + self.board.device) + return Disk(disks[0]) + + @property + def info(self): + with self.disk as disk: + fname = os.path.join(disk.path, 'INFO_UF2.TXT') + with open(fname, 'r') as f: + info = f.read() + lines = info.splitlines() + res = {} + res['header'] = lines[0] + for line in lines[1:]: + k, _, v = line.partition(':') + res[k.replace(':', '')] = v.strip() + return res + + def upload(self, fw): + with open(fw, 'rb') as f: + header = f.read(32) + if header[0:4] != b'UF2\n': + raise ValueError('Only UF2 files are supported') + self.board.close() + with self.disk as disk: + disk.copy(fw, sync=False) + + +class CPboard: + @classmethod + def from_try_all(cls, name, **kwargs): + try: + return CPboard.from_build_name(name, **kwargs) + except ValueError: + pass + + vendor, _, product = name.partition(':') + if vendor and product: + return CPboard.from_usb(**kwargs, idVendor=int(vendor, 16), idProduct=int(product, 16)) + + return CPboard(name, **kwargs) + + @classmethod + def from_build_name(cls, name, **kwargs): + boards = { + #'arduino_zero' + 'circuitplayground_express' : (0x239a, 0x8019), + #'feather_m0_adalogger' : (0x239a, ), + #'feather_m0_basic' : (0x239a, ), + 'feather_m0_express' : (0x239a, 0x8023), + #'feather_m0_rfm69' : (0x239a, ), + #'feather_m0_rfm9x' : (0x239a, ), + #'feather_m0_supersized' : (0x239a, ), + #'feather_m4_express' : (0x239a, ), + #'gemma_m0' : (0x239a, ), + #'itsybitsy_m0_express' : (0x239a, ), + #'itsybitsy_m4_express' : (0x239a, ), + 'metro_m0_express' : (0x239a, 0x8014), + 'metro_m4_express' : (0x239a, 0x8021), + #'metro_m4_express_revb' : (0x239a, ), + #'pirkey_m0' : (0x239a, ), + #'trinket_m0' : (0x239a, ), + #'trinket_m0_haxpress' : (0x239a, ), + #'ugame10' + } + + try: + vendor, product = boards[name] + except KeyError: + raise ValueError("Unknown build name: " + name) + + return CPboard.from_usb(**kwargs, idVendor=vendor, idProduct=product) + + @classmethod + def from_build_name_bootloader(cls, name, **kwargs): + boards = { + #'arduino_zero' + #'circuitplayground_express' : (0x239a, ), + #'feather_m0_adalogger' : (0x239a, ), + #'feather_m0_basic' : (0x239a, ), + 'feather_m0_express' : (0x239a, 0x001b), + #'feather_m0_rfm69' : (0x239a, ), + #'feather_m0_rfm9x' : (0x239a, ), + #'feather_m0_supersized' : (0x239a, ), + #'feather_m4_express' : (0x239a, ), + #'gemma_m0' : (0x239a, ), + #'itsybitsy_m0_express' : (0x239a, ), + #'itsybitsy_m4_express' : (0x239a, ), + #'metro_m0_express' : (0x239a, 0x8014), + 'metro_m4_express' : (0x239a, 0x0021), + #'metro_m4_express_revb' : (0x239a, ), + #'pirkey_m0' : (0x239a, ), + #'trinket_m0' : (0x239a, ), + #'trinket_m0_haxpress' : (0x239a, ), + #'ugame10' + } + + try: + vendor, product = boards[name] + except KeyError: + raise ValueError("Unknown build name: " + name) + + board = CPboard.from_usb(**kwargs, idVendor=vendor, idProduct=product) + board.bootloader = True + return board + + @classmethod + def from_usb(cls, baudrate=115200, wait=0, timeout=10, **kwargs): + import usb.core + dev = usb.core.find(**kwargs) + if not dev: + s = "Can't find USB device: " + args = [] + for x in kwargs.items(): + try: + args.append('%s=0x%x' % x) + except: + args.append('%s = %s' % x) + raise RuntimeError("Can't find USB device: " + ', '.join(args)) + return cls(dev, baudrate=baudrate, wait=wait, timeout=timeout) + + def __init__(self, device, baudrate=115200, wait=0, timeout=10): + self.device = device + self.usb_dev = None + try: + # Is it a usb.core.Device? + portstr = ':' + '.'.join(map(str, device.port_numbers)) + ':' + except: + pass + else: + serials = [serial for serial in os.listdir("/dev/serial/by-path") if portstr in serial] + if len(serials) != 1: + raise RuntimeError("Can't find excatly one matching usb serial device") + self.device = os.path.realpath("/dev/serial/by-path/" + serials[0]) + self.usb_dev = device + + self.baudrate = baudrate + self.wait = wait + self.timeout = timeout + self.debug = True + self.mount = None + self.serial = None + self.bootloader = False + self.repl = REPL(self) + + def __enter__(self): + self.open() + return self + + def __exit__(self, exception_type, exception_value, traceback): + self.close() + + def open(self, baudrate=None, wait=None): + if self.serial: + return + if baudrate is None: + baudrate = self.baudrate + if wait is None: + wait = self.wait + + delayed = False + for attempt in range(wait + 1): + try: + self.serial = serial.Serial(self.device, baudrate=self.baudrate, timeout=self.timeout, write_timeout=self.timeout, interCharTimeout=1) + break + except (OSError, IOError): # Py2 and Py3 have different errors + if wait == 0: + continue + if attempt == 0: + sys.stdout.write('Waiting {} seconds for board '.format(wait)) + delayed = True + time.sleep(1) + sys.stdout.write('.') + sys.stdout.flush() + else: + if delayed: + print('') + raise CPboardError('failed to access ' + self.device) + if delayed: + print('') + + def close(self): + if self.serial: + self.serial.close() + self.serial = None + + def exec(self, command, timeout=10, async=False): + with self.repl as repl: + try: + output, error = repl.execute(command, timeout=timeout, async=async) + except OSError as e: + if self.debug: + print('exec: session: ', self.repl.session) + raise CPboardError('timeout', e) + if error: + raise CPboardError('exception', output, error) + return output + + def eval(self, expression, timeout=10): + command = 'print({})'.format(expression) + with self.repl as repl: + output, error = repl.execute(command, timeout=timeout) + if error: + raise CPboardError('exception', output, error) + try: + res = eval(str(output, encoding='utf8')) + except: + raise CPboardError('failed to eval: %s' % output) + return res + + def _reset(self, mode='NORMAL'): + self.exec("import microcontroller;microcontroller.on_next_reset(microcontroller.RunMode.%s)" % mode) + try: + self.exec("import microcontroller;microcontroller.reset()", async=True) + except OSError: + pass + + def reset(self, safe_mode=False, delay=5, wait=10): + self._reset('SAFE_MODE' if safe_mode else 'NORMAL') + self.close() + time.sleep(delay) + self.open(wait) + time.sleep(delay) + + def reset_to_bootloader(self, repl=False): + if repl: + self._reset('BOOTLOADER') + self.close() + else: + self.close() + s = serial.Serial(self.device, 1200, write_timeout=4, timeout=4) + s.close() + + def get_port_info(self): + portinfo = None + for port_iter in serial.tools.list_ports.comports(): + if port_iter.device == self.device: + portinfo = port_iter + break + return portinfo + + @property + def serial_number(self): + try: # Permissions are needed to read the value + return self.usb_dev.serial_number + except: + pass + p = self.get_port_info() + return p.serial_number if p else None + + def get_disks(self): + if self.usb_dev: + portstr = ':' + '.'.join(map(str, self.usb_dev.port_numbers)) + ':' + return ["/dev/disk/by-path/" + disk for disk in os.listdir("/dev/disk/by-path") if portstr in disk] + serial = self.serial_number + if not serial: + raise RuntimeError("Serial number not found for: " + self.device) + return ["/dev/disk/by-id/" + disk for disk in os.listdir("/dev/disk/by-id") if serial in disk] + + @property + def disk(self): + disks = self.get_disks() + + part = [part for part in disks if 'part1' in part] + if not part: + raise RuntimeError("Disk not found for: " + self.device) + + return Disk(part[0]) + + @property + def firmware(self): + return Firmware(self) + + def execfile_disk(self, filename): + with self.disk as disk: + disk.copy(filename, 'code.py') + + with self.repl as repl: + try: + output = repl.run() + except OSError as e: + raise CPboardError('timeout', e) + except RuntimeError: + if self.repl.safe_mode: + raise PyboardError("Can't run in safe mode") + else: + raise + + return output + + def execfile(self, filename, timeout=10): + if os.environ.get('CPBOARD_EXEC_MODE') == 'disk': + return self.execfile_disk(filename) + else: + with open(filename, 'rb') as f: + pyfile = f.read() + return self.exec(pyfile, timeout=timeout) + + +# Implement just enough to make tests/run-tests work +PyboardError = CPboardError + +class Pyboard: + def __init__(self, device, baudrate=115200, user='micro', password='python', wait=0): + self.board = CPboard.from_try_all(device, baudrate=baudrate, wait=wait) + with self.board.disk as disk: + disk.copy('skip_if.py') + + def close(self): + self.board.close() + + def enter_raw_repl(self): + self.board.open() + + def execfile(self, filename): + return self.board.execfile(filename) + + +def eval_namedtuple(board, command): + from collections import namedtuple + s = board.exec("print(%s)" % command) + s = s.decode().strip() + items = [key.split('=') for key in s[1:-1].split(', ')] + keys = [item[0] for item in items] + vals = [item[1] for item in items] + nt = namedtuple('eval', keys) + res = nt(*[eval(val) for val in vals]) + return res + + +def os_uname(board): + return eval_namedtuple(board, "__import__('os').uname()") + +def print_verbose(cargs, *args, **kwargs): + if cargs.verbose: + print(*args, flush=True, **kwargs) + +def upload(args): + try: + board = CPboard.from_build_name_bootloader(args.board) + print_verbose(args, 'Board is already in the bootloader') + except (ValueError, RuntimeError): + board = CPboard.from_try_all(args.board) + + print_verbose(args, "Serial number :", board.serial_number) + + if not (args.quiet or board.bootloader): + board.open() + print('Current version:', os_uname(board).version, flush=True) + + if not board.bootloader: + print_verbose(args, 'Reset to bootloader...', end='') + board.reset_to_bootloader(repl=True) # Feather M0 Express doesn't respond to 1200 baud + time.sleep(5) + print_verbose(args, 'done') + + print_verbose(args, 'Bootloader:', board.firmware.info) + + print_verbose(args, 'Upload firmware...', end='') + board.firmware.upload(args.firmware) + print_verbose(args, 'done') + + print_verbose(args, 'Wait for board...', end='') + time.sleep(5) + print_verbose(args, 'done') + + if not args.quiet: + if board.bootloader: + board = CPboard.from_try_all(args.board) + board.open(wait=10) + print('New version:', os_uname(board).version, flush=True) + +def print_error_exit(args, e): + if args.debug: + return False + if not args.quiet: + print(e, file=sys.stderr) + sys.exit(1) + +def main(): + import argparse + cmd_parser = argparse.ArgumentParser(description='Circuit Python Board Tool') + cmd_parser.add_argument('board', help='build_name, vid:pid or /dev/tty') + cmd_parser.add_argument('-f', '--firmware', help='upload UF2 firmware file') + cmd_parser.add_argument('-c', '--command', help='program passed in as string') + cmd_parser.add_argument('--tty', action='store_true', help='print tty') + cmd_parser.add_argument('--verbose', '-v', action='count', default=0, help='be verbose') + cmd_parser.add_argument('-q', '--quiet', action='store_true', help='be quiet') + cmd_parser.add_argument('--debug', action='store_true', help='raise exceptions') + args = cmd_parser.parse_args() + + if args.quiet: + args.verbose = 0 + args.debug = False + + if args.firmware: + try: + upload(args) + except BaseException as e: + if not print_error_exit(args, e): + raise + sys.exit(0) + + try: + board = CPboard.from_try_all(args.board) + except BaseException as e: + if not print_error_exit(args, e): + raise + + if args.verbose: + exec_mode = os.environ.get('CPBOARD_EXEC_MODE') + if exec_mode: + print('CPBOARD_EXEC_MODE =', exec_mode) + + # Make sure we can open serial + try: + with board: + pass + except BaseException as e: + if not print_error_exit(args, e): + raise + + if args.tty: + print(board.device) + elif args.command: + with board as b: + print(b.eval(args.command)) + else: + with board as b: + print('Device: ', end='') + if b.usb_dev: + print('%04x:%04x on ' % (b.usb_dev.idVendor, b.usb_dev.idProduct), end='') + print(b.device) + print('Serial number:', b.serial_number) + uname = os_uname(b) + print('os.uname:') + print(' sysname:', uname.sysname) + print(' nodename:', uname.nodename) + print(' release:', uname.release) + print(' version:', uname.version) + print(' machine:', uname.machine) + +if __name__ == "__main__": + main()