diff options
| author | Dan Halbert <halbert@halwitz.org> | 2018-04-02 19:19:43 -0400 |
|---|---|---|
| committer | Dan Halbert <halbert@halwitz.org> | 2018-04-02 19:19:43 -0400 |
| commit | 435e894fa0ec5e9ce82b7bdef308413c6731e06a (patch) | |
| tree | af8d62363157a6ba969684538e012871a88224c6 | |
| parent | d005b123267ab4ac2f0471c730b762cc3e94232c (diff) | |
| parent | 98c7d70fe406d66d80c3c9cc888602f96cf444c4 (diff) | |
Merge branch 'master' into 3.0_hid
85 files changed, 768 insertions, 1202 deletions
diff --git a/.gitmodules b/.gitmodules index a7f31837a..ec0b01e33 100644 --- a/.gitmodules +++ b/.gitmodules @@ -33,9 +33,6 @@ path = lib/stm32lib url = https://github.com/micropython/stm32lib branch = work-F4-1.13.1+F7-1.5.0+L4-1.3.0 -[submodule "freetouch2"] - path = ports/atmel-samd/freetouch - url = https://github.com/adafruit/Adafruit_FreeTouch.git [submodule "atmel-samd/asf4"] path = ports/atmel-samd/asf4 url = https://github.com/adafruit/asf4.git @@ -46,3 +43,6 @@ [submodule "lib/nrfutil"] path = lib/nrfutil url = https://github.com/adafruit/nRF52_nrfutil +[submodule "ports/atmel-samd/freetouch"] + path = ports/atmel-samd/freetouch + url = https://github.com/adafruit/Adafruit_FreeTouch.git diff --git a/.travis.yml b/.travis.yml index a69840333..94f7059b0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ env: - TRAVIS_BOARD=feather_m0_rfm69 - TRAVIS_BOARD=feather_m0_rfm9x - TRAVIS_BOARD=feather_m0_express + - TRAVIS_BOARD=feather_m4_express - TRAVIS_BOARD=itsybitsy_m0_express - TRAVIS_BOARD=metro_m0_express - TRAVIS_BOARD=metro_m4_express @@ -77,24 +78,24 @@ script: - echo -en 'travis_fold:end:qemu\\r' # run tests without coverage info - #- (cd tests && MICROPY_CPYTHON3=python3.4 ./run-tests) - #- (cd tests && MICROPY_CPYTHON3=python3.4 ./run-tests --emit native) + #- (cd tests && MICROPY_CPYTHON3=python3.4 ./run-tests -j1) + #- (cd tests && MICROPY_CPYTHON3=python3.4 ./run-tests -j1 --emit native) # run tests with coverage info - echo 'Test all' && echo -en 'travis_fold:start:test_all\\r' - - ([[ $TRAVIS_TEST != "unix" ]] || (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests)) + - ([[ $TRAVIS_TEST != "unix" ]] || (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1)) - echo -en 'travis_fold:end:test_all\\r' - echo 'Test threads' && echo -en 'travis_fold:start:test_threads\\r' - - ([[ $TRAVIS_TEST != "unix" ]] || (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -d thread)) + - ([[ $TRAVIS_TEST != "unix" ]] || (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 -d thread)) - echo -en 'travis_fold:end:test_threads\\r' - echo 'Testing with native' && echo -en 'travis_fold:start:test_native\\r' - - ([[ $TRAVIS_TEST != "unix" ]] || (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --emit native)) + - ([[ $TRAVIS_TEST != "unix" ]] || (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 --emit native)) - echo -en 'travis_fold:end:test_native\\r' - (echo 'Testing with mpy' && echo -en 'travis_fold:start:test_mpy\\r') - - ([[ $TRAVIS_TEST != "unix" ]] || (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --via-mpy -d basics float)) + - ([[ $TRAVIS_TEST != "unix" ]] || (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 --via-mpy -d basics float)) - echo -en 'travis_fold:end:test_mpy\\r' - (echo 'Building docs' && echo -en 'travis_fold:start:build_docs\\r') diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5401892dd..2eb0214da 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,8 +8,7 @@ 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 and -[Gitter](gitter.im/adafruit/circuitpython) as tannewt during US West Coast +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 diff --git a/README.rst b/README.rst index 7e234331e..31c0cce59 100644 --- a/README.rst +++ b/README.rst @@ -83,8 +83,7 @@ Conduct <https://github.com/adafruit/circuitpython/blob/master/CODE_OF_CONDUCT.m Contributors who follow the `Code of Conduct <https://github.com/adafruit/circuitpython/blob/master/CODE_OF_CONDUCT.md>`__ are welcome to submit pull requests and they will be promptly reviewed -by project admins. Please join the `Gitter -chat <https://gitter.im/adafruit/circuitpython>`__ or +by project admins. Please join the `Discord <https://discord.gg/nBQh6qu>`__ too. -------------- diff --git a/docs/drivers.rst b/docs/drivers.rst index 523316b09..951967e09 100644 --- a/docs/drivers.rst +++ b/docs/drivers.rst @@ -76,6 +76,7 @@ Multi-color led drivers. NeoPixel <https://circuitpython.readthedocs.io/projects/neopixel/en/latest/> DotStar <https://circuitpython.readthedocs.io/projects/dotstar/en/latest/> + WS2801 <https://circuitpython.readthedocs.io/projects/ws2801/en/latest/> Displays ------------- @@ -111,7 +112,7 @@ Motion relating sensing including ``acceleration``, ``magnetic``, ``gyro``, and .. toctree:: BNO055 Accelerometer, Magnetometer, Gyroscope and Absolution Orientation <https://circuitpython.readthedocs.io/projects/bno055/en/latest/> - FXAS21002C Gyroscope <https://circuitpython.readthedocs.io/projects/fxas21002C/en/latest/> + FXAS21002C Gyroscope <https://circuitpython.readthedocs.io/projects/fxas21002c/en/latest/> FXOS8700 Accelerometer <https://circuitpython.readthedocs.io/projects/fxos8700/en/latest/> GPS Global Position <https://circuitpython.readthedocs.io/projects/gps/en/latest/> LIS3DH Accelerometer <https://circuitpython.readthedocs.io/projects/lis3dh/en/latest/> @@ -154,6 +155,7 @@ These sensors detect light related attributes such as ``color``, ``light`` (unit .. toctree:: APDS9960 Proximity, Light, RGB, and Gesture <https://circuitpython.readthedocs.io/projects/apds9960/en/latest/> + AS726x Color Spectrum Sensor <https://circuitpython.readthedocs.io/projects/as726x/en/latest/> TCS34725 Color Sensor <https://circuitpython.readthedocs.io/projects/tcs34725/en/latest/> TSL2561 Light Sensor <https://circuitpython.readthedocs.io/projects/tsl2561/en/latest/> TSL2591 High Dynamic Range Light Sensor <https://circuitpython.readthedocs.io/projects/tsl2591/en/latest/> @@ -191,6 +193,7 @@ These provide functionality similar to `analogio`, `digitalio`, `pulseio`, and ` ADS1x15 Analog-to-Digital Converter <https://circuitpython.readthedocs.io/projects/ads1x15/en/latest/> DS2413 OneWire GPIO Expander <https://circuitpython.readthedocs.io/projects/ds2413/en/latest/> FocalTech Capacitive Touch <https://circuitpython.readthedocs.io/projects/focaltouch/en/latest/> + MCP230xx GPIO Expander <https://circuitpython.readthedocs.io/projects/mcp230xx/en/latest/> MCP4725 Digital-to-Analog Converter <https://circuitpython.readthedocs.io/projects/mcp4725/en/latest/> PCA9685 16 x 12-bit PWM Driver <https://circuitpython.readthedocs.io/projects/pca9685/en/latest/> TLC5947 24 x 12-bit PWM Driver <https://circuitpython.readthedocs.io/projects/tlc5947/en/latest/> diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 22346bdf1..81ca1e23d 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -33,6 +33,7 @@ #endif #include <string.h> +#include "py/objproperty.h" #include "py/runtime.h" #include "py/mperrno.h" #include "lib/oofatfs/ff.h" @@ -317,6 +318,39 @@ STATIC mp_obj_t vfs_fat_umount(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, vfs_fat_umount); +#if MICROPY_FATFS_USE_LABEL +STATIC mp_obj_t vfs_fat_getlabel(mp_obj_t self_in) { + fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); + char working_buf[12]; + FRESULT res = f_getlabel(&self->fatfs, working_buf, NULL); + if (res != FR_OK) { + mp_raise_OSError(fresult_to_errno_table[res]); + } + return mp_obj_new_str(working_buf, strlen(working_buf), false); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getlabel_obj, vfs_fat_getlabel); + +static mp_obj_t vfs_fat_setlabel(mp_obj_t self_in, mp_obj_t label_in) { + fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); + const char *label_str = mp_obj_str_get_str(label_in); + FRESULT res = f_setlabel(&self->fatfs, label_str); + if (res != FR_OK) { + if(res == FR_WRITE_PROTECTED) { + mp_raise_msg(&mp_type_OSError, "Read-only filesystem"); + } + mp_raise_OSError(fresult_to_errno_table[res]); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_setlabel_obj, vfs_fat_setlabel); +STATIC const mp_obj_property_t fat_vfs_label_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&fat_vfs_getlabel_obj, + (mp_obj_t)&fat_vfs_setlabel_obj, + (mp_obj_t)&mp_const_none_obj}, +}; +#endif + STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) }, @@ -331,6 +365,9 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&fat_vfs_statvfs_obj) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_fat_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&fat_vfs_umount_obj) }, +#if MICROPY_FATFS_USE_LABEL + { MP_ROM_QSTR(MP_QSTR_label), MP_ROM_PTR(&fat_vfs_label_obj) }, +#endif }; STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table); diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index f580184a7..be9c8c792 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -125,11 +125,7 @@ STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, break; case 1: // SEEK_CUR - if (s->offset != 0) { - *errcode = MP_EOPNOTSUPP; - return MP_STREAM_ERROR; - } - // no-operation + f_lseek(&self->fp, f_tell(&self->fp) + s->offset); break; case 2: // SEEK_END diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 49823c0de..39625ad95 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -72,7 +72,6 @@ BASE_CFLAGS = \ -Wnested-externs \ -Wunreachable-code \ -Wcast-align \ - -Wno-error=lto-type-mismatch \ -D__$(CHIP_VARIANT)__ \ -ffunction-sections \ -fdata-sections \ diff --git a/ports/atmel-samd/README.rst b/ports/atmel-samd/README.rst index 8785ccada..d475e3816 100644 --- a/ports/atmel-samd/README.rst +++ b/ports/atmel-samd/README.rst @@ -115,16 +115,54 @@ PB03 **Yes** **Yes** **Yes** **Yes** Setup ----- -Install required compiler packages: + +An ARM compiler is required for the build, along with the associated binary +utilities. On Ubuntu, these can be installed as follows: .. code-block:: shell sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa sudo apt-get install gcc-arm-embedded +On Arch Linux the compiler is available for via the package +``arm-none-eabi-gcc``. + +For other systems, the `GNU Arm Embedded Toolchain <https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads>`_ +may be available in binary form. + +The latest available package from team-gcc-arm-embedded is used to produce the +binaries shipped by AdaFruit. Other compiler versions, particularly older +ones, may not work properly. In particular, the ``gcc-arm-none-eabi`` package +in Debian Stretch is too old. + +The compiler can be changed using the ``CROSS_COMPILE`` variable when invoking +``make``. + Building -------- +Before building the firmware for a given board, there are two additional steps. +These commands should be executed from the root directory of the repository +(``circuitpython/``). + +1. There are various submodules that reside in different repositories. In order + to have these submodules locally, you must pull them into your clone, using: + +.. code-block:: shell + + git submodule update --init --recursive + +2. The MicroPython cross-compiler must be built; it will be used to pre-compile + some of the built-in scripts to bytecode. The cross-compiler is built and + run on the host machine, using: + +.. code-block:: shell + + make -C mpy-cross + + +Build commands are run from the ``circuitpython/ports/atmel-samd`` directory. + To build for the Arduino Zero: .. code-block:: shell diff --git a/ports/atmel-samd/boards/circuitplayground_express/pins.c b/ports/atmel-samd/boards/circuitplayground_express/pins.c index 4be74f377..aecd7f416 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/pins.c +++ b/ports/atmel-samd/boards/circuitplayground_express/pins.c @@ -2,17 +2,25 @@ 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) }, diff --git a/ports/atmel-samd/boards/feather_m4_express/board.c b/ports/atmel-samd/boards/feather_m4_express/board.c new file mode 100644 index 000000000..8096b9b8e --- /dev/null +++ b/ports/atmel-samd/boards/feather_m4_express/board.c @@ -0,0 +1,38 @@ +/* + * 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 "boards/board.h" +#include "mpconfigboard.h" + +void board_init(void) { +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h new file mode 100644 index 000000000..bd56a7bdf --- /dev/null +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h @@ -0,0 +1,34 @@ +#define MICROPY_HW_BOARD_NAME "Feather M4 Express" +#define MICROPY_HW_MCU_NAME "samd51j19" + +#define CIRCUITPY_MCU_FAMILY samd51 + +// This is for Rev C which is green + +#define MICROPY_HW_NEOPIXEL (&pin_PB23) + +// 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 ) +#define MICROPY_PORT_C (0) +#define MICROPY_PORT_D (0) + +#define AUTORESET_DELAY_MS 500 + +// 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 CIRCUITPY_INTERNAL_NVM_SIZE 0 + +#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 W25Q16FW, GD25Q16C + +#define EXTERNAL_FLASH_QSPI_DUAL + +#include "external_flash/external_flash.h" diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk new file mode 100644 index 000000000..61620ffa2 --- /dev/null +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk @@ -0,0 +1,10 @@ +LD_FILE = boards/samd51x19-bootloader-external-flash.ld +USB_VID = 0x239A +USB_PID = 0x8026 +USB_PRODUCT = "Feather M4 Express" +USB_MANUFACTURER = "Adafruit Industries LLC" + +QSPI_FLASH_FILESYSTEM = 1 + +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 new file mode 100644 index 000000000..c161e736e --- /dev/null +++ b/ports/atmel-samd/boards/feather_m4_express/pins.c @@ -0,0 +1,30 @@ +#include "samd21_pins.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_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_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_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_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 4baafcb11..6457d481f 100644 --- a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h @@ -1,8 +1,8 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Gemma 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 diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h index b541af80c..e2b7f9982 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h @@ -3,18 +3,18 @@ #define CIRCUITPY_MCU_FAMILY samd51 -// This is for Rev D which is light blue +// This is for Rev F which is green #define MICROPY_HW_LED_TX PIN_PA27 #define MICROPY_HW_LED_RX PIN_PB06 -#define MICROPY_HW_NEOPIXEL (&pin_PB17) +#define MICROPY_HW_NEOPIXEL (&pin_PB22) // These are pins not to reset. // QSPI Data pins and TX LED #define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11 | PORT_PA27) // RX LED, QSPI CS, QSPI SCK and NeoPixel pin -#define MICROPY_PORT_B ( PORT_PB06 | PORT_PB10 | PORT_PB11 | PORT_PB17) +#define MICROPY_PORT_B ( PORT_PB06 | PORT_PB10 | PORT_PB11 | PORT_PB22) #define MICROPY_PORT_C (0) #define MICROPY_PORT_D (0) diff --git a/ports/atmel-samd/boards/metro_m4_express/pins.c b/ports/atmel-samd/boards/metro_m4_express/pins.c index 33b69b32b..32ecdf492 100644 --- a/ports/atmel-samd/boards/metro_m4_express/pins.c +++ b/ports/atmel-samd/boards/metro_m4_express/pins.c @@ -7,36 +7,37 @@ 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_PB09 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A3), (mp_obj_t)&pin_PA04 }, { MP_OBJ_NEW_QSTR(MP_QSTR_A4), (mp_obj_t)&pin_PB08 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A5), (mp_obj_t)&pin_PA07 }, - + { MP_OBJ_NEW_QSTR(MP_QSTR_A5), (mp_obj_t)&pin_PB09 }, { 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_PA04 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D2), (mp_obj_t)&pin_PB17 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D3), (mp_obj_t)&pin_PB16 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D4), (mp_obj_t)&pin_PB13 }, { 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_D7), (mp_obj_t)&pin_PB12 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D8), (mp_obj_t)&pin_PA21 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D9), (mp_obj_t)&pin_PA20 }, { 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_D12), (mp_obj_t)&pin_PA17 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D13), (mp_obj_t)&pin_PA16 }, { 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_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 }, { 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_MISO), (mp_obj_t)&pin_PA14 }, { 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 }, diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c index 4182c8651..77676b535 100644 --- a/ports/atmel-samd/common-hal/busio/I2C.c +++ b/ports/atmel-samd/common-hal/busio/I2C.c @@ -34,6 +34,7 @@ #include "peripherals.h" #include "pins.h" +#include "shared-bindings/microcontroller/__init__.h" // Number of times to try to send packet if failed. @@ -46,19 +47,21 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, uint32_t sda_pinmux = 0; uint32_t scl_pinmux = 0; for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { - Sercom* potential_sercom = sda->sercom[i].sercom; - if (potential_sercom == NULL || - potential_sercom->I2CM.CTRLA.bit.ENABLE != 0 || + sercom_index = sda->sercom[i].index; + if (sercom_index >= SERCOM_INST_NUM) { + continue; + } + Sercom* potential_sercom = sercom_insts[sercom_index]; + if (potential_sercom->I2CM.CTRLA.bit.ENABLE != 0 || sda->sercom[i].pad != 0) { continue; } sda_pinmux = PINMUX(sda->pin, (i == 0) ? MUX_C : MUX_D); for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { - if (potential_sercom == scl->sercom[j].sercom && + if (sercom_index == scl->sercom[j].index && scl->sercom[j].pad == 1) { scl_pinmux = PINMUX(scl->pin, (j == 0) ? MUX_C : MUX_D); sercom = potential_sercom; - sercom_index = scl->sercom[j].index; // 2 for SERCOM2, etc. break; } } @@ -70,24 +73,46 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, mp_raise_ValueError("Invalid pins"); } + // Test that the pins are in a high state. (Hopefully indicating they are pulled up.) + gpio_set_pin_function(sda->pin, GPIO_PIN_FUNCTION_OFF); + gpio_set_pin_function(scl->pin, GPIO_PIN_FUNCTION_OFF); + gpio_set_pin_direction(sda->pin, GPIO_DIRECTION_IN); + gpio_set_pin_direction(scl->pin, GPIO_DIRECTION_IN); + + gpio_set_pin_pull_mode(sda->pin, GPIO_PULL_DOWN); + gpio_set_pin_pull_mode(scl->pin, GPIO_PULL_DOWN); + + common_hal_mcu_delay_us(10); + + gpio_set_pin_pull_mode(sda->pin, GPIO_PULL_OFF); + gpio_set_pin_pull_mode(scl->pin, GPIO_PULL_OFF); + + // We must pull up within 3us to achieve 400khz. + common_hal_mcu_delay_us(3); + + if (!gpio_get_pin_level(sda->pin) || !gpio_get_pin_level(scl->pin)) { + reset_pin(sda->pin); + reset_pin(scl->pin); + mp_raise_RuntimeError("SDA or SCL needs a pull up"); + } + gpio_set_pin_function(sda->pin, sda_pinmux); + gpio_set_pin_function(scl->pin, scl_pinmux); // Set up I2C clocks on sercom. samd_peripherals_sercom_clock_init(sercom, sercom_index); if (i2c_m_sync_init(&self->i2c_desc, sercom) != ERR_NONE) { - mp_raise_OSError(MP_EIO); + reset_pin(sda->pin); + reset_pin(scl->pin); + mp_raise_OSError(MP_EIO); } - - gpio_set_pin_pull_mode(sda->pin, GPIO_PULL_OFF); - gpio_set_pin_function(sda->pin, sda_pinmux); - - gpio_set_pin_pull_mode(scl->pin, GPIO_PULL_OFF); - gpio_set_pin_function(scl->pin, scl_pinmux); // clkrate is always 0. baud_rate is in kHz. - + // Frequency must be set before the I2C device is enabled. if (i2c_m_sync_set_baudrate(&self->i2c_desc, 0, frequency / 1000) != ERR_NONE) { + reset_pin(sda->pin); + reset_pin(scl->pin); mp_raise_ValueError("Unsupported baudrate"); } @@ -113,7 +138,7 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { i2c_m_sync_disable(&self->i2c_desc); i2c_m_sync_deinit(&self->i2c_desc); - + reset_pin(self->sda_pin); reset_pin(self->scl_pin); self->sda_pin = NO_PIN; diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index eca73be78..a2bf30f05 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -55,9 +55,12 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, uint8_t miso_pad = 0; uint8_t dopo = 255; for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { - Sercom* potential_sercom = clock->sercom[i].sercom; sercom_index = clock->sercom[i].index; // 2 for SERCOM2, etc. - if (potential_sercom == NULL || + if (sercom_index >= SERCOM_INST_NUM) { + continue; + } + Sercom* potential_sercom = sercom_insts[sercom_index]; + if ( #if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !defined(CIRCUITPY_BITBANG_APA102) (potential_sercom->SPI.CTRLA.bit.ENABLE != 0 && potential_sercom != status_apa102.spi_desc.dev.prvt && @@ -74,7 +77,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, } for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { if (!mosi_none) { - if(potential_sercom == mosi->sercom[j].sercom) { + if (sercom_index == mosi->sercom[j].index) { mosi_pinmux = PINMUX(mosi->pin, (j == 0) ? MUX_C : MUX_D); mosi_pad = mosi->sercom[j].pad; dopo = samd_peripherals_get_spi_dopo(clock_pad, mosi_pad); @@ -91,7 +94,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, } if (!miso_none) { for (int k = 0; k < NUM_SERCOMS_PER_PIN; k++) { - if (potential_sercom == miso->sercom[k].sercom) { + if (sercom_index == miso->sercom[k].index) { miso_pinmux = PINMUX(miso->pin, (k == 0) ? MUX_C : MUX_D); miso_pad = miso->sercom[k].pad; sercom = potential_sercom; diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c index 292e01e60..537677520 100644 --- a/ports/atmel-samd/common-hal/busio/UART.c +++ b/ports/atmel-samd/common-hal/busio/UART.c @@ -56,7 +56,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, uint8_t bits, uart_parity_t parity, uint8_t stop, uint32_t timeout, uint8_t receiver_buffer_size) { Sercom* sercom = NULL; - uint8_t sercom_index; + uint8_t sercom_index = 255; // Unset index uint32_t rx_pinmux = 0; uint8_t rx_pad = 255; // Unset pad uint32_t tx_pinmux = 0; @@ -71,7 +71,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, if (!have_tx && !have_rx) { mp_raise_ValueError("tx and rx cannot both be None"); } - + self->baudrate = baudrate; self->character_bits = bits; self->timeout_ms = timeout; @@ -82,10 +82,12 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { Sercom* potential_sercom = NULL; if (have_tx) { - potential_sercom = tx->sercom[i].sercom; sercom_index = tx->sercom[i].index; - if (potential_sercom == NULL || - potential_sercom->USART.CTRLA.bit.ENABLE != 0 || + if (sercom_index >= SERCOM_INST_NUM) { + continue; + } + potential_sercom = sercom_insts[sercom_index]; + if (potential_sercom->USART.CTRLA.bit.ENABLE != 0 || !(tx->sercom[i].pad == 0 || tx->sercom[i].pad == 2)) { continue; @@ -98,12 +100,13 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, } } for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { - if (((!have_tx && rx->sercom[j].sercom->USART.CTRLA.bit.ENABLE == 0) || - potential_sercom == rx->sercom[j].sercom) && + if (((!have_tx && rx->sercom[j].index < SERCOM_INST_NUM && + sercom_insts[rx->sercom[j].index]->USART.CTRLA.bit.ENABLE == 0) || + sercom_index == rx->sercom[j].index) && rx->sercom[j].pad != tx_pad) { rx_pinmux = PINMUX(rx->pin, (j == 0) ? MUX_C : MUX_D); rx_pad = rx->sercom[j].pad; - sercom = rx->sercom[j].sercom; + sercom = sercom_insts[rx->sercom[j].index]; sercom_index = rx->sercom[j].index; break; } @@ -147,7 +150,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, // usart_async_init() sets a number of defaults based on a prototypical SERCOM // which don't necessarily match what we need. After calling it, set the values // specific to this instantiation of UART. - + // Set pads computed for this SERCOM. // TXPO: // 0x0: TX pad 0; no RTS/CTS @@ -182,7 +185,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, // http://start.atmel.com/static/help/index.html?GUID-79201A5A-226F-4FBB-B0B8-AB0BE0554836 // Look at the ASFv4 code example for async USART. usart_async_register_callback(usart_desc_p, USART_ASYNC_RXC_CB, usart_async_rxc_callback); - + if (have_tx) { gpio_set_pin_direction(tx->pin, GPIO_DIRECTION_OUT); @@ -193,7 +196,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, } else { self->tx_pin = NO_PIN; } - + if (have_rx) { gpio_set_pin_direction(rx->pin, GPIO_DIRECTION_IN); gpio_set_pin_pull_mode(rx->pin, GPIO_PULL_OFF); @@ -238,7 +241,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t // Nothing to read. return 0; } - + struct io_descriptor *io; usart_async_get_io_descriptor(usart_desc_p, &io); @@ -266,7 +269,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t MICROPY_VM_HOOK_LOOP #endif } - + return total_read; } @@ -305,7 +308,7 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } - + struct usart_async_status async_status; // Could return ERR_BUSY, but if that's true there's already a problem. usart_async_get_status(usart_desc_p, &async_status); diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.h b/ports/atmel-samd/common-hal/microcontroller/Pin.h index ca639eb84..4e21a14cd 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Pin.h +++ b/ports/atmel-samd/common-hal/microcontroller/Pin.h @@ -34,9 +34,8 @@ #include "include/component/sercom.h" typedef struct { - Sercom *const sercom; // SERCOM0, SERCOM1, etc. - uint8_t index; // 0, 1, etc. corresponding to SERCOM<n>. - uint8_t pad; // which of the four SERCOM pads to use + uint8_t index:6; // 0, 1, etc. corresponding to SERCOM<n>. + uint8_t pad:2; // which of the four SERCOM pads to use } pin_sercom_t; typedef struct { diff --git a/ports/atmel-samd/common-hal/microcontroller/Processor.c b/ports/atmel-samd/common-hal/microcontroller/Processor.c index 1c57808f7..5c0d72c96 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Processor.c +++ b/ports/atmel-samd/common-hal/microcontroller/Processor.c @@ -243,7 +243,7 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { for (int i=0; i<4; i++) { for (int k=0; k<4; k++) { - raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xf; + raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xff; } } } diff --git a/ports/atmel-samd/external_flash/common_commands.h b/ports/atmel-samd/external_flash/common_commands.h index fc05e70de..bb2060708 100644 --- a/ports/atmel-samd/external_flash/common_commands.h +++ b/ports/atmel-samd/external_flash/common_commands.h @@ -35,7 +35,11 @@ #define CMD_PAGE_PROGRAM 0x02 // #define CMD_PAGE_PROGRAM CMD_READ_JEDEC_ID #define CMD_READ_STATUS 0x05 +#define CMD_READ_STATUS2 0x35 #define CMD_WRITE_STATUS_BYTE1 0x01 +#define CMD_DUAL_READ 0x3b #define CMD_QUAD_READ 0x6b +#define CMD_ENABLE_RESET 0x66 +#define CMD_RESET 0x99 #endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_COMMON_COMMANDS_H diff --git a/ports/atmel-samd/external_flash/devices.h b/ports/atmel-samd/external_flash/devices.h index ce2c6c3dc..d8baf5aca 100644 --- a/ports/atmel-samd/external_flash/devices.h +++ b/ports/atmel-samd/external_flash/devices.h @@ -169,7 +169,7 @@ typedef struct { .supports_qspi_writes = true, \ } -// Settings for the Winbond W25Q32BV 2MiB SPI flash. +// Settings for the Winbond W25Q32BV 4MiB SPI flash. // Datasheet: https://www.winbond.com/resource-files/w25q32bv_revi_100413_wo_automotive.pdf #define W25Q32BV {\ .total_size = (1 << 22), /* 4 MiB */ \ diff --git a/ports/atmel-samd/external_flash/external_flash.c b/ports/atmel-samd/external_flash/external_flash.c index 304bf6462..ccc47e5b1 100644 --- a/ports/atmel-samd/external_flash/external_flash.c +++ b/ports/atmel-samd/external_flash/external_flash.c @@ -185,12 +185,11 @@ void external_flash_init(void) { if (flash_device != NULL) { return; } - uint8_t num_possible_devices = sizeof(*possible_devices) / sizeof(external_flash_device); // Delay to give the SPI Flash time to get going. // TODO(tannewt): Only do this when we know power was applied vs a reset. uint16_t max_start_up_delay_us = 0; - for (uint8_t i = 0; i < num_possible_devices; i++) { + for (uint8_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) { if (possible_devices[i].start_up_time_us > max_start_up_delay_us) { max_start_up_delay_us = possible_devices[i].start_up_time_us; } @@ -199,10 +198,14 @@ void external_flash_init(void) { spi_flash_init(); - for (uint8_t i = 0; i < num_possible_devices; i++) { - const external_flash_device* possible_device = &possible_devices[i]; - uint8_t jedec_id_response[3] = {0x00, 0x00, 0x00}; + // The response will be 0xff if the flash needs more time to start up. + uint8_t jedec_id_response[3] = {0xff, 0xff, 0xff}; + while (jedec_id_response[0] == 0xff) { spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3); + } + + for (uint8_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) { + const external_flash_device* possible_device = &possible_devices[i]; if (jedec_id_response[0] == possible_device->manufacturer_id && jedec_id_response[1] == possible_device->memory_type && jedec_id_response[2] == possible_device->capacity) { @@ -215,6 +218,26 @@ void external_flash_init(void) { return; } + // We don't know what state the flash is in so wait for any remaining writes and then reset. + uint8_t read_status_response[1] = {0x00}; + // The write in progress bit should be low. + do { + spi_flash_read_command(CMD_READ_STATUS, read_status_response, 1); + } while ((read_status_response[0] & 0x1) != 0); + // The suspended write/erase bit should be low. + do { + spi_flash_read_command(CMD_READ_STATUS2, read_status_response, 1); + } while ((read_status_response[0] & 0x80) != 0); + + + spi_flash_command(CMD_ENABLE_RESET); + spi_flash_command(CMD_RESET); + + // Wait 30us for the reset + common_hal_mcu_delay_us(30); + + spi_flash_init_device(flash_device); + // Activity LED for flash writes. #ifdef MICROPY_HW_LED_MSC gpio_set_pin_function(SPI_FLASH_CS_PIN, GPIO_PIN_FUNCTION_OFF); diff --git a/ports/atmel-samd/external_flash/qspi_flash.c b/ports/atmel-samd/external_flash/qspi_flash.c index 46e3cb92a..f4d5ec904 100644 --- a/ports/atmel-samd/external_flash/qspi_flash.c +++ b/ports/atmel-samd/external_flash/qspi_flash.c @@ -29,6 +29,8 @@ #include <stdint.h> #include <string.h> +#include "mpconfigboard.h" // for EXTERNAL_FLASH_QSPI_DUAL + #include "external_flash/common_commands.h" #include "shared_dma.h" @@ -139,8 +141,13 @@ bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) { } bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) { + #ifdef EXTERNAL_FLASH_QSPI_DUAL + QSPI->INSTRCTRL.bit.INSTR = CMD_DUAL_READ; + uint32_t mode = QSPI_INSTRFRAME_WIDTH_DUAL_OUTPUT; + #else QSPI->INSTRCTRL.bit.INSTR = CMD_QUAD_READ; uint32_t mode = QSPI_INSTRFRAME_WIDTH_QUAD_OUTPUT; + #endif QSPI->INSTRFRAME.reg = mode | QSPI_INSTRFRAME_ADDRLEN_24BITS | @@ -174,7 +181,7 @@ void spi_flash_init(void) { // Slow, good for debugging with Saleae // QSPI->BAUD.bit.BAUD = 32; - // Super fast + // Super fast, may be unreliable when Saleae is connected to high speed lines. QSPI->BAUD.bit.BAUD = 2; QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY | QSPI_CTRLB_DATALEN_8BITS | @@ -189,14 +196,17 @@ void spi_flash_init(void) { gpio_set_pin_pull_mode(pins[i], GPIO_PULL_OFF); gpio_set_pin_function(pins[i], GPIO_PIN_FUNCTION_H); } +} +void spi_flash_init_device(const external_flash_device* device) { // Verify that QSPI mode is enabled. uint8_t status; - spi_flash_read_command(0x35, &status, 1); + spi_flash_read_command(CMD_READ_STATUS2, &status, 1); + // Bit 1 is Quad Enable if ((status & 0x2) == 0) { - uint8_t full_status[3] = { 0, status | 0x2, 0x70}; + uint8_t full_status[2] = { 0x0, 0x2}; spi_flash_command(CMD_ENABLE_WRITE); - spi_flash_write_command(0x01, full_status, 3); + spi_flash_write_command(CMD_WRITE_STATUS_BYTE1, full_status, 2); } } diff --git a/ports/atmel-samd/external_flash/spi_flash.c b/ports/atmel-samd/external_flash/spi_flash.c index fcaedcaac..8a8cbaef8 100644 --- a/ports/atmel-samd/external_flash/spi_flash.c +++ b/ports/atmel-samd/external_flash/spi_flash.c @@ -152,3 +152,7 @@ void spi_flash_init(void) { spi_m_sync_enable(&spi_flash_desc); } + +void spi_flash_init_device(const external_flash_device* device) { + +} diff --git a/ports/atmel-samd/external_flash/spi_flash_api.h b/ports/atmel-samd/external_flash/spi_flash_api.h index b858ff0ea..a6df0c459 100644 --- a/ports/atmel-samd/external_flash/spi_flash_api.h +++ b/ports/atmel-samd/external_flash/spi_flash_api.h @@ -29,6 +29,8 @@ #include <stdbool.h> #include <stdint.h> +#include "external_flash/devices.h" + // This API is implemented for both normal SPI peripherals and QSPI peripherals. bool spi_flash_command(uint8_t command); @@ -38,5 +40,6 @@ bool spi_flash_sector_command(uint8_t command, uint32_t address); bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length); bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length); void spi_flash_init(void); +void spi_flash_init_device(const external_flash_device* device); #endif // MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H diff --git a/ports/atmel-samd/freetouch b/ports/atmel-samd/freetouch new file mode 160000 +Subproject c3deba11eb4be397ec719cfbfba1abcaecda2c0 diff --git a/ports/atmel-samd/freetouch/Adafruit_FreeTouch.cpp b/ports/atmel-samd/freetouch/Adafruit_FreeTouch.cpp deleted file mode 100644 index 45cac3867..000000000 --- a/ports/atmel-samd/freetouch/Adafruit_FreeTouch.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* - * FreeTouch, a QTouch-compatible library - tested on ATSAMD21 only! - * The MIT License (MIT) - * - * Copyright (c) 2017 Limor 'ladyada' Fried 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 "Adafruit_FreeTouch.h" - -#include "adafruit_ptc.h" - -Adafruit_FreeTouch::Adafruit_FreeTouch(int p, oversample_t f, series_resistor_t r, freq_mode_t fh) { - adafruit_ptc_get_config_default(&config); - pin = p; - uint8_t port_offset = 0; - if (g_APinDescription[pin].ulPort == PORTB) { - port_offset += 32; - } - config.pin = port_offset + g_APinDescription[pin].ulPin; - config.yline = getYLine(); // determine the Y0-15 # - config.oversample = f; - config.seriesres = r; - config.freqhop = fh; -} - -bool Adafruit_FreeTouch::begin(void) { - if (config.yline == -1) { // not all pins have Y line - return false; - } - - /* 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); - */ - - uint8_t channel = PTC_GCLK_ID; - uint8_t source_generator = 1; - - // original line: system_gclk_chan_set_config(PTC_GCLK_ID, &gclk_chan_conf); - uint32_t new_clkctrl_config = (channel << GCLK_CLKCTRL_ID_Pos); // from gclk.c - - // original line: gclk_chan_conf.source_generator = GCLK_GENERATOR_1; - /* Select the desired generic clock generator */ - new_clkctrl_config |= source_generator << GCLK_CLKCTRL_GEN_Pos; // from gclk.c - - /* Disable generic clock channel */ - // original line: system_gclk_chan_disable(channel); - noInterrupts(); - - /* Select the requested generator channel */ - *((uint8_t*)&GCLK->CLKCTRL.reg) = channel; - - /* Sanity check WRTLOCK */ - //Assert(!GCLK->CLKCTRL.bit.WRTLOCK); - - /* Switch to known-working source so that the channel can be disabled */ - uint32_t prev_gen_id = GCLK->CLKCTRL.bit.GEN; - GCLK->CLKCTRL.bit.GEN = 0; - - /* Disable the generic clock */ - GCLK->CLKCTRL.reg &= ~GCLK_CLKCTRL_CLKEN; - while (GCLK->CLKCTRL.reg & GCLK_CLKCTRL_CLKEN) { - /* Wait for clock to become disabled */ - } - - /* Restore previous configured clock generator */ - GCLK->CLKCTRL.bit.GEN = prev_gen_id; - - //system_interrupt_leave_critical_section(); - interrupts(); - - /* Write the new configuration */ - GCLK->CLKCTRL.reg = new_clkctrl_config; - - // original line: system_gclk_chan_enable(PTC_GCLK_ID); - *((uint8_t*)&GCLK->CLKCTRL.reg) = channel; - GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_CLKEN; /* Enable the generic clock */ - - - // original line: system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_PTC); - PM->APBCMASK.reg |= PM_APBCMASK_PTC; - - adafruit_ptc_init(PTC, &config); - - return true; -} - -uint16_t Adafruit_FreeTouch::measure(void) { - uint16_t m; - - m = measureRaw(); - if (m == -1) return -1; - - // normalize the signal - switch (config.oversample) { - case OVERSAMPLE_1: return m; - case OVERSAMPLE_2: return m/2; - case OVERSAMPLE_4: return m/4; - case OVERSAMPLE_8: return m/8; - case OVERSAMPLE_16: return m/16; - case OVERSAMPLE_32: return m/32; - case OVERSAMPLE_64: return m/64; - } - - return -1; // shouldn't reach here but fail if we do! -} - -uint16_t Adafruit_FreeTouch::measureRaw(void) { - adafruit_ptc_start_conversion(PTC, &config); - - while (!adafruit_ptc_is_conversion_finished(PTC)) { - yield(); - } - - return adafruit_ptc_get_conversion_result(PTC); -} - -/*********************************** low level config **/ - -int Adafruit_FreeTouch::getYLine(void) { - int p = g_APinDescription[pin].ulPin; - if (g_APinDescription[pin].ulPort == PORTA) { - if ((p >= 2) && (p <= 7)) { - return (p - 2); - } - } - if (g_APinDescription[pin].ulPort == PORTB) { - if ((p >= 0) && (p <= 9)) { - return (p + 6); - } - } - - // not valid - return -1; -} - -void Adafruit_FreeTouch::setCompCap(uint16_t cc) { - config.compcap = cc & 0x3FFF; -} - -void Adafruit_FreeTouch::setIntCap(uint8_t ic) { - config.intcap = ic & 0x3F; -} - -void Adafruit_FreeTouch::setOversampling(oversample_t lvl) { - config.oversample = lvl; // back it up for later -} - -void Adafruit_FreeTouch::setSeriesResistor(series_resistor_t res) { - config.seriesres = res; -} - -void Adafruit_FreeTouch::setFreqHopping(freq_mode_t fh, freq_hop_t hs) { - config.freqhop = fh; - config.hops = hs; -} - -/**************************** DEBUGGING ASSIST *************************/ -void Adafruit_FreeTouch::snapshotRegsAndPrint(uint32_t base, uint8_t numregs) { - volatile uint32_t addr = base; - uint8_t datas[255]; - - digitalWrite(LED_BUILTIN, HIGH); - for (uint8_t i=0; i<numregs; i++) { - datas[i] = *(uint8_t *)(addr+i); - } - digitalWrite(LED_BUILTIN, LOW); - printPTCregs(base, datas, numregs); - - for (uint8_t i=0; i<numregs; i++) { - // Serial.print("$"); Serial.print(addr+i, HEX); Serial.print("\t0x"); - // printHex(datas[i]); Serial.println(); - } - -} - -// Print a hex with leading zero -void Adafruit_FreeTouch::printHex(uint8_t h, boolean newline) { - if (h < 0x10) Serial.print("0"); - Serial.print(h, HEX); - if (newline) Serial.println(); -} - -void Adafruit_FreeTouch::printPTCregs(uint32_t base, uint8_t *regs, uint8_t num) { - Serial.println("--------------------------------------------------------"); - for (uint8_t i=0; i<num; i++) { - switch (i + base) { - case 0x41004430: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" PMUX0:\t\t0x"); printHex(regs[i], true); break; - case 0x41004431: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" PMUX1:\t\t0x"); printHex(regs[i], true); break; - case 0x41004432: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" PMUX2:\t\t0x"); printHex(regs[i], true); break; - case 0x41004433: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" PMUX3:\t\t0x"); printHex(regs[i], true); break; - - case 0x41004440: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" PCFG0:\t\t0x"); printHex(regs[i], true); break; - case 0x41004441: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" PCFG1:\t\t0x"); printHex(regs[i], true); break; - case 0x41004442: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" PCFG2:\t\t0x"); printHex(regs[i], true); break; - case 0x41004443: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" PCFG3:\t\t0x"); printHex(regs[i], true); break; - case 0x41004444: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" PCFG4:\t\t0x"); printHex(regs[i], true); break; - - - case 0x42004C00: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Control A:\t\t0x"); printHex(regs[i], true); break; - case 0x42004C01: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Sync: \t\t0x"); printHex(regs[i], true); break; - case 0x42004C04: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Prescaler:\t\t0x"); printHex(regs[i], true); break; - case 0x42004C05: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Init: \t\t0x"); printHex(regs[i], true); break; - case 0x42004C08: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Disable Irq:\t\t0x"); printHex(regs[i], true); break; - case 0x42004C09: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Enable Irq:\t\t0x"); printHex(regs[i], true); break; - case 0x42004C0A: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Flags: \t\t0x"); printHex(regs[i], true); break; - case 0x42004C0C: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Freq Cntl:\t\t0x"); printHex(regs[i], true); break; - case 0x42004C0D: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Conv Cntl:\t\t0x"); printHex(regs[i], true); break; - case 0x42004C10: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Y Select1:\t\t0x"); printHex(regs[i], true); break; - case 0x42004C11: Serial.print("0x"); Serial.print(i+0x42004C00, HEX); - Serial.print(" Y Select2:\t\t0x"); printHex(regs[i], true); break; -/* - case 0x42004C12: Serial.print("0x"); Serial.print(i+0x42004C00, HEX); - Serial.print(" X Select1:\t\t0x"); printHex(regs[i], true); break; - case 0x42004C13: Serial.print("0x"); Serial.print(i+0x42004C00, HEX); - Serial.print(" X Select2:\t\t0x"); printHex(regs[i], true); break; -*/ - case 0x42004C14: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Y Enable1:\t\t0x"); printHex(regs[i], true); break; - case 0x42004C15: Serial.print("0x"); Serial.print(i+0x42004C00, HEX); - Serial.print(" Y Enable2:\t\t0x"); printHex(regs[i], true); break; -/* - case 0x42004C16: Serial.print("0x"); Serial.print(i+0x42004C00, HEX); - Serial.print(" X Enable1:\t\t0x"); printHex(regs[i], true); break; - case 0x42004C17: Serial.print("0x"); Serial.print(i+0x42004C00, HEX); - Serial.print(" X Enable2:\t\t0x"); printHex(regs[i], true); break; -*/ - case 0x42004C18: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Compcap L:\t\t0x"); printHex(regs[i], true); break; - case 0x42004C19: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Compcap H:\t\t0x"); printHex(regs[i], true); break; - case 0x42004C1A: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Intcap: \t\t0x"); printHex(regs[i], true); break; - case 0x42004C1B: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Sense res:\t\t0x"); printHex(regs[i], true); break; - case 0x42004C1C: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Result L:\t\t0x"); printHex(regs[i], true); break; - case 0x42004C1D: Serial.print("0x"); Serial.print(i+base, HEX); - Serial.print(" Result H:\t\t0x"); printHex(regs[i], true); break; - - } - } -} diff --git a/ports/atmel-samd/freetouch/Adafruit_FreeTouch.h b/ports/atmel-samd/freetouch/Adafruit_FreeTouch.h deleted file mode 100644 index 85dd08988..000000000 --- a/ports/atmel-samd/freetouch/Adafruit_FreeTouch.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef ADAFRUIT_FREETOUCH_H -#define ADAFRUIT_FREETOUCH_H - -#include <Arduino.h> -#include "adafruit_ptc.h" - -class Adafruit_FreeTouch { - public: - Adafruit_FreeTouch(int p = 0, oversample_t f = OVERSAMPLE_4, series_resistor_t r = RESISTOR_0, freq_mode_t fh = FREQ_MODE_NONE); - bool begin(void); - - uint16_t measure(void); - uint16_t measureRaw(void); - - private: - void ptcInitSettings(void); - void ptcConfigIOpin(void); - uint16_t startPtcAcquire(void); - - int getYLine(void); - void selectYLine(void); - void setOversampling(oversample_t lvl); - void setSeriesResistor(series_resistor_t res); - void setFreqHopping(freq_mode_t fh, freq_hop_t hops = FREQ_HOP_1); - void setCompCap(uint16_t cc); - void setIntCap(uint8_t ic); - - void snapshotRegsAndPrint(uint32_t base, uint8_t numregs); - void printHex(uint8_t h, boolean newline); - void printPTCregs(uint32_t base, uint8_t *regs, uint8_t num); - - private: - int pin; // arduino pin # - struct adafruit_ptc_config config; -}; - -#endif diff --git a/ports/atmel-samd/freetouch/README.md b/ports/atmel-samd/freetouch/README.md deleted file mode 100644 index 3b179a45c..000000000 --- a/ports/atmel-samd/freetouch/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Adafruit_FreeTouch -A QTouch-compatible library diff --git a/ports/atmel-samd/freetouch/adafruit_ptc.c b/ports/atmel-samd/freetouch/adafruit_ptc.c deleted file mode 100644 index f4369cf4a..000000000 --- a/ports/atmel-samd/freetouch/adafruit_ptc.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * FreeTouch, a QTouch-compatible library - tested on ATSAMD21 only! - * The MIT License (MIT) - * - * Copyright (c) 2017 Limor 'ladyada' Fried 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 "adafruit_ptc.h" -#include "pinmux.h" - -static void sync_config(Ptc const* module_inst) { - while (module_inst->CONTROLB.bit.SYNCFLAG) ; -} - -void adafruit_ptc_get_config_default(struct adafruit_ptc_config *config) { - config->pin = 0xff; - config->yline = -1; - config->oversample = OVERSAMPLE_4; - config->seriesres = RESISTOR_0; - config->freqhop = FREQ_MODE_NONE; - config->compcap = 0x2000; - config->intcap = 0x3F; -} - -void adafruit_ptc_init(Ptc* module_inst, struct adafruit_ptc_config const* config) { - struct system_pinmux_config pinmux_config; - system_pinmux_get_config_defaults(&pinmux_config); - pinmux_config.mux_position = 0x1; - pinmux_config.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE; - system_pinmux_pin_set_config(config->pin, &pinmux_config); - - sync_config(module_inst); - module_inst->CONTROLA.bit.ENABLE = 0; - sync_config(module_inst); - - module_inst->UNK4C04.reg &= 0xF7; //MEMORY[0x42004C04] &= 0xF7u; - module_inst->UNK4C04.reg &= 0xFB; //MEMORY[0x42004C04] &= 0xFBu; - module_inst->UNK4C04.reg &= 0xFC; //MEMORY[0x42004C04] &= 0xFCu; - sync_config(module_inst); - module_inst->FREQCONTROL.reg &= 0x9F; //MEMORY[0x42004C0C] &= 0x9Fu; - sync_config(module_inst); - module_inst->FREQCONTROL.reg &= 0xEF; //MEMORY[0x42004C0C] &= 0xEFu; - sync_config(module_inst); - module_inst->FREQCONTROL.bit.SAMPLEDELAY = 0; //MEMORY[0x42004C0C] &= 0xF0u; - module_inst->CONTROLC.bit.INIT = 1; //MEMORY[0x42004C05] |= 1u; - module_inst->CONTROLA.bit.RUNINSTANDBY = 1; //MEMORY[0x42004C00] |= 4u; - sync_config(module_inst); - module_inst->INTDISABLE.bit.WCO = 1; - sync_config(module_inst); - module_inst->INTDISABLE.bit.EOC = 1; - sync_config(module_inst); - - // enable the sensor, only done once per line - if (config->yline < 8) { - sync_config(module_inst); - module_inst->YENABLEL.reg |= 1 << config->yline; - sync_config(module_inst); - } else if (config->yline < 16) { - module_inst->YENABLEH.reg |= 1 << (config->yline - 8); - } - - sync_config(module_inst); - module_inst->CONTROLA.bit.ENABLE = 1; - sync_config(module_inst); -} - -void adafruit_ptc_start_conversion(Ptc* module_inst, struct adafruit_ptc_config const* config) { - module_inst->CONTROLA.bit.RUNINSTANDBY = 1; - sync_config(module_inst); - module_inst->CONTROLA.bit.ENABLE = 1; - sync_config(module_inst); - module_inst->INTDISABLE.bit.WCO = 1; - sync_config(module_inst); - module_inst->INTFLAGS.bit.WCO = 1; - sync_config(module_inst); - module_inst->INTFLAGS.bit.EOC = 1; - sync_config(module_inst); - - // set up pin! - sync_config(module_inst); - if (config->yline < 8) { - module_inst->YSELECTL.reg = 1 << config->yline; - } else { - module_inst->YSELECTL.reg = 0; - } - - if (config->yline > 7) { - module_inst->YSELECTH.reg = 1 << (config->yline - 8); - } else { - module_inst->YSELECTH.reg = 0; - } - - sync_config(module_inst); - // set up sense resistor - module_inst->SERRES.bit.RESISTOR = config->seriesres; - sync_config(module_inst); - // set up prescalar - module_inst->CONVCONTROL.bit.ADCACCUM = config->oversample; - sync_config(module_inst); - // set up freq hopping - if (config->freqhop == FREQ_MODE_NONE) { - module_inst->FREQCONTROL.bit.FREQSPREADEN = 0; - module_inst->FREQCONTROL.bit.SAMPLEDELAY = 0; - } else { - module_inst->FREQCONTROL.bit.FREQSPREADEN = 1; - module_inst->FREQCONTROL.bit.SAMPLEDELAY = config->hops; - } - // set up compensation cap + int (?) cap - sync_config(module_inst); - module_inst->COMPCAPL.bit.VALUE = config->compcap & 0xFF; - module_inst->COMPCAPH.bit.VALUE = (config->compcap>>8) & 0x3F; - sync_config(module_inst); - module_inst->INTCAP.bit.VALUE = config->intcap & 0x3F; - sync_config(module_inst); - - module_inst->BURSTMODE.reg = 0xA4; - sync_config(module_inst); - - module_inst->CONVCONTROL.bit.CONVERT = 1; - sync_config(module_inst); -} - -bool adafruit_ptc_is_conversion_finished(Ptc* module_inst) { - return module_inst->CONVCONTROL.bit.CONVERT == 0; -} - -uint16_t adafruit_ptc_get_conversion_result(Ptc* module_inst) { - sync_config(module_inst); - return module_inst->RESULT.reg; -} diff --git a/ports/atmel-samd/freetouch/adafruit_ptc.h b/ports/atmel-samd/freetouch/adafruit_ptc.h deleted file mode 100644 index 93bb16ef4..000000000 --- a/ports/atmel-samd/freetouch/adafruit_ptc.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * FreeTouch, a QTouch-compatible library - tested on ATSAMD21 only! - * The MIT License (MIT) - * - * Copyright (c) 2017 Limor 'ladyada' Fried 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. - */ - -// This is similar to the drivers found in sam0/drivers but for the PTC. -#ifndef ADAFRUIT_FREETOUCH_ADAFRUIT_PTC_H -#define ADAFRUIT_FREETOUCH_ADAFRUIT_PTC_H - -#include <stdint.h> - -#include "samd21_ptc_component.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Touch library oversampling (filter) setting */ -typedef enum tag_oversample_level_t { - OVERSAMPLE_1, - OVERSAMPLE_2, - OVERSAMPLE_4, - OVERSAMPLE_8, - OVERSAMPLE_16, - OVERSAMPLE_32, - OVERSAMPLE_64 -} -oversample_t; - -/* Touch library series resistor setting */ -typedef enum tag_series_resistor_t { - RESISTOR_0, - RESISTOR_20K, - RESISTOR_50K, - RESISTOR_100K, -} -series_resistor_t; - -typedef enum tag_freq_mode_t { - FREQ_MODE_NONE, - FREQ_MODE_HOP, - FREQ_MODE_SPREAD, - FREQ_MODE_SPREAD_MEDIAN -} -freq_mode_t; - -typedef enum tag_freq_hop_t { - FREQ_HOP_1, - FREQ_HOP_2, - FREQ_HOP_3, - FREQ_HOP_4, - FREQ_HOP_5, - FREQ_HOP_6, - FREQ_HOP_7, - FREQ_HOP_8, - FREQ_HOP_9, - FREQ_HOP_10, - FREQ_HOP_11, - FREQ_HOP_12, - FREQ_HOP_13, - FREQ_HOP_14, - FREQ_HOP_15, - FREQ_HOP_16 -} -freq_hop_t; - -struct adafruit_ptc_config { - uint8_t pin; // ASF pin # - int8_t yline; // the Y select line (see datasheet) - oversample_t oversample; - series_resistor_t seriesres; - freq_mode_t freqhop; - freq_hop_t hops; - uint16_t compcap; - uint8_t intcap; -}; - -void adafruit_ptc_get_config_default(struct adafruit_ptc_config *config); -void adafruit_ptc_init(Ptc* module_inst, struct adafruit_ptc_config const* config); -void adafruit_ptc_start_conversion(Ptc* module_inst, struct adafruit_ptc_config const* config); - -bool adafruit_ptc_is_conversion_finished(Ptc* module_inst); -uint16_t adafruit_ptc_get_conversion_result(Ptc* module_inst); - -#ifdef __cplusplus -} -#endif - -#endif // ADAFRUIT_FREETOUCH_ADAFRUIT_PTC_H diff --git a/ports/atmel-samd/freetouch/examples/freetouch/freetouch.ino b/ports/atmel-samd/freetouch/examples/freetouch/freetouch.ino deleted file mode 100644 index d89642c2e..000000000 --- a/ports/atmel-samd/freetouch/examples/freetouch/freetouch.ino +++ /dev/null @@ -1,56 +0,0 @@ -#include "Adafruit_FreeTouch.h" - -Adafruit_FreeTouch qt_1 = Adafruit_FreeTouch(A0, OVERSAMPLE_4, RESISTOR_50K, FREQ_MODE_NONE); -Adafruit_FreeTouch qt_2 = Adafruit_FreeTouch(A1, OVERSAMPLE_4, RESISTOR_50K, FREQ_MODE_NONE); -Adafruit_FreeTouch qt_3 = Adafruit_FreeTouch(A2, OVERSAMPLE_4, RESISTOR_50K, FREQ_MODE_NONE); -Adafruit_FreeTouch qt_4 = Adafruit_FreeTouch(A3, OVERSAMPLE_4, RESISTOR_50K, FREQ_MODE_NONE); - -void setup() { - Serial.begin(115200); - - while (!Serial); - Serial.println("FreeTouch test"); - // initialize digital pin LED_BUILTIN as an output. - pinMode(LED_BUILTIN, OUTPUT); - - if (! qt_1.begin()) - Serial.println("Failed to begin qt on pin A0"); - if (! qt_2.begin()) - Serial.println("Failed to begin qt on pin A1"); - if (! qt_3.begin()) - Serial.println("Failed to begin qt on pin A2"); - if (! qt_4.begin()) - Serial.println("Failed to begin qt on pin A3"); - -} - - - -void loop() { - int counter, result = 0; - - // DIY - Serial.println("\n*************************************"); - - counter = millis(); - result = qt_1.measure(); - Serial.print("QT 1: "); Serial.print(result); - Serial.print(" ("); Serial.print(millis() - counter); Serial.println(" ms)"); - - counter = millis(); - result = qt_2.measure(); - Serial.print("QT 2: "); Serial.print(result); - Serial.print(" ("); Serial.print(millis() - counter); Serial.println(" ms)"); - - counter = millis(); - result = qt_3.measure(); - Serial.print("QT 3: "); Serial.print(result); - Serial.print(" ("); Serial.print(millis() - counter); Serial.println(" ms)"); - - counter = millis(); - result = qt_4.measure(); - Serial.print("QT 4: "); Serial.print(result); - Serial.print(" ("); Serial.print(millis() - counter); Serial.println(" ms)"); - - delay(200); -}
\ No newline at end of file diff --git a/ports/atmel-samd/freetouch/samd21_ptc_component.h b/ports/atmel-samd/freetouch/samd21_ptc_component.h deleted file mode 100644 index 0af3236d3..000000000 --- a/ports/atmel-samd/freetouch/samd21_ptc_component.h +++ /dev/null @@ -1,350 +0,0 @@ -/* - * FreeTouch, a QTouch-compatible library - tested on ATSAMD21 only! - * The MIT License (MIT) - * - * Copyright (c) 2017 Limor 'ladyada' Fried 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. - */ - -// This is similar to the component definitions found in -// sam0/utils/cmsis/samd21/include/component but for the PTC. -#ifndef ADAFRUIT_FREETOUCH_PTC_COMPONENT_H -#define ADAFRUIT_FREETOUCH_PTC_COMPONENT_H - -#include "compiler.h" - -#undef ENABLE - -/*************** CONTROL A register ***************/ -#define PTC_REG_CONTROLA 0x42004C00 -#define PTC_BIT_ENABLE 0x02 -#define PTC_BIT_RUNINSTBY 0x04 - - -typedef union { - struct { - uint8_t SWRESET:1; - uint8_t ENABLE:1; - uint8_t RUNINSTANDBY:1; - uint8_t __pad0__:5; - } bit; - uint8_t reg; -} PTC_REG_CONTROLA_Type; - -/*************** CONTROL B register ***************/ - -#define PTC_REG_CONTROLB 0x42004C01 -#define PTC_BIT_SYNCFLAG 0x80 - -typedef union { - struct { - uint8_t __pad0__:7; - uint8_t SYNCFLAG:1; - } bit; - uint8_t reg; -} PTC_REG_CONTROLB_Type; - -/*************** UNK4C04 register ***************/ - -#define PTC_REG_UNK4C04 0x42004C04 - -typedef union { - uint8_t reg; -} PTC_REG_UNK4C04_Type; - - -/*************** CONTROL C register ***************/ - -#define PTC_REG_CONTROLC 0x42004C05 -#define PTC_BIT_INIT 0x01 - -typedef union { - struct { - uint8_t INIT:1; - uint8_t __pad0__:7; - } bit; - uint8_t reg; -} PTC_REG_CONTROLC_Type; - - - -/*************** INT registers ***************/ - -typedef union { - struct { - uint8_t EOC:1; - uint8_t WCO:1; - uint8_t __pad0__:6; - } bit; - uint8_t reg; -} PTC_REG_INT_Type; - - -#define PTC_REG_INTDISABLE 0x42004C08 -#define PTC_REG_INTENABLE 0x42004C09 -#define PTC_BIT_EOCINTEN 0x01 -#define PTC_BIT_WCOINTEN 0x02 - -#define PTC_REG_INTFLAGS 0x42004C0A -#define PTC_BIT_EOCINTFLAG 0x01 -#define PTC_BIT_WCOINTFLAG 0x02 - - -/*************** FREQ CONTROL reg ***************/ - -typedef union { - struct { - uint8_t SAMPLEDELAY:4; - uint8_t FREQSPREADEN:1; - uint8_t __pad0__:3; - } bit; - uint8_t reg; -} PTC_REG_FREQCONTROL_Type; - -#define PTC_REG_FREQCONTROL 0x42004C0C -#define PTC_BIT_FREQSPREADEN 0x10 -#define PTC_REG_SAMPLEDELAY_MASK 0x0F - -/*************** CONVERT CONTROL reg ***************/ - -typedef union { - struct { - uint8_t ADCACCUM:3; - uint8_t __pad0__:4; - uint8_t CONVERT:1; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_CONVCONTROL_Type; - - -#define PTC_REG_CONVCONTROL 0x42004C0D -#define PTC_BIT_CONVSTARTED 0x80 -#define PTC_REG_ADCACC_MASK 0x07 - - -/*************** Y SELECT L+H reg ***************/ - -typedef union { - struct { - uint8_t Y0:1; - uint8_t Y1:1; - uint8_t Y2:1; - uint8_t Y3:1; - uint8_t Y4:1; - uint8_t Y5:1; - uint8_t Y6:1; - uint8_t Y7:1; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_YSELECTL_Type; - -typedef union { - struct { - uint8_t Y8:1; - uint8_t Y9:1; - uint8_t Y10:1; - uint8_t Y11:1; - uint8_t Y12:1; - uint8_t Y13:1; - uint8_t Y14:1; - uint8_t Y15:1; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_YSELECTH_Type; - -#define PTC_REG_YSELECT_L 0x42004C10 -#define PTC_REG_YSELECT_H 0x42004C11 - -#define PTC_REG_YENABLE_L 0x42004C14 -#define PTC_REG_YENABLE_H 0x42004C15 - - -/*************** X SELECT L+H reg ***************/ - -typedef union { - struct { - uint8_t X0:1; - uint8_t X1:1; - uint8_t X2:1; - uint8_t X3:1; - uint8_t X4:1; - uint8_t X5:1; - uint8_t X6:1; - uint8_t X7:1; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_XSELECTL_Type; - -typedef union { - struct { - uint8_t X8:1; - uint8_t X9:1; - uint8_t X10:1; - uint8_t X11:1; - uint8_t X12:1; - uint8_t X13:1; - uint8_t X14:1; - uint8_t X15:1; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_XSELECTH_Type; - - -#define PTC_REG_XSELECT_L 0x42004C12 -#define PTC_REG_XSELECT_H 0x42004C13 - -#define PTC_REG_XENABLE_L 0x42004C16 -#define PTC_REG_XENABLE_H 0x42004C17 - -/*************** Compensation Cap reg ***************/ - -typedef union { - struct { - uint8_t VALUE:8; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_COMPCAPL_Type; - -typedef union { - struct { - uint8_t VALUE:6; - uint8_t __pad0__:2; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_COMPCAPH_Type; - -#define PTC_REG_COMPCAPL 0x42004C18 -#define PTC_REG_COMPCAPH 0x42004C19 - -/*************** Int Cap reg ***************/ - -typedef union { - struct { - uint8_t VALUE:6; - uint8_t __pad0__:2; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_INTCAP_Type; - - -#define PTC_REG_INTCAP 0x42004C1A - -/*************** Series resistor reg ***************/ - -typedef union { - struct { - uint8_t RESISTOR:2; - uint8_t __pad0__:6; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_SERRES_Type; - -#define PTC_REG_SERIESRES 0x42004C1B - -/*************** conversion result reg ***************/ - -typedef union { - struct { - uint8_t LOWBYTE; - uint8_t HIGHBYTE; - } byte; - uint16_t reg; -} __attribute__ ((packed)) PTC_REG_CONVRESULT_Type; - -#define PTC_REG_CONVRESULT_L 0x42004C1C -#define PTC_REG_CONVRESULT_H 0x42004C1D - -/*************** burst mode reg ***************/ - -typedef union { - struct { - uint8_t __pad0__:2; - uint8_t CTSLOWPOWER:1; - uint8_t __pad1__:1; - uint8_t BURSTMODE:4; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_BURSTMODE_Type; - - -#define PTC_REG_BURSTMODE 0x42004C20 -#define PTC_REG_BURSTMODE_MASK 0xF0 -#define PTC_BIT_CTSLOWPOWER 0x04 - -/*************** etc unused reg ***************/ - -#define PTC_REG_XYENABLE 0x42004C16 -#define PTC_BIT_XYENABLE 0x02 - -#define PTC_REG_WCO_MODE 0x42004C21 -#define PTC_REG_WCO_MODE_MASK 0x07 - -#define PTC_SET_WCO_THRESHHOLD_A_L 0x42004C24 -#define PTC_SET_WCO_THRESHHOLD_A_H 0x42004C25 -#define PTC_SET_WCO_THRESHHOLD_B_L 0x42004C26 -#define PTC_SET_WCO_THRESHHOLD_B_H 0x42004C27 - -typedef struct { - __IO PTC_REG_CONTROLA_Type CONTROLA; // 0x42004C00 - __IO PTC_REG_CONTROLB_Type CONTROLB; // 0x42004C01 - uint8_t __pad4c02__; // 0x42004C02 unknown - uint8_t __pad4c03__; // 0x42004C03 unknown - __IO PTC_REG_UNK4C04_Type UNK4C04; // 0x42004C04 unknown - __IO PTC_REG_CONTROLC_Type CONTROLC; // 0x42004C05 - uint8_t __pad4c06__; // 0x42004C06 unknown - uint8_t __pad4c07__; // 0x42004C07 unknown - __IO PTC_REG_INT_Type INTDISABLE; // 0x42004C08 - __IO PTC_REG_INT_Type INTENABLE; // 0x42004C09 - __IO PTC_REG_INT_Type INTFLAGS; // 0x42004C0A - uint8_t __pad4c0b__; // 0x42004C0B unknown - __IO PTC_REG_FREQCONTROL_Type FREQCONTROL; //0x42004C0C - __IO PTC_REG_CONVCONTROL_Type CONVCONTROL; // 0x42004C0D - uint8_t __pad4c0e__; // 0x42004C0E unknown - uint8_t __pad4c0f__; // 0x42004C0F unknown - __IO PTC_REG_YSELECTL_Type YSELECTL; // 0x42004C10 - __IO PTC_REG_YSELECTL_Type YSELECTH; // 0x42004C11 - __IO PTC_REG_XSELECTL_Type XSELECTL; // 0x42004C12 - __IO PTC_REG_XSELECTL_Type XSELECTH; // 0x42004C13 - __IO PTC_REG_YSELECTL_Type YENABLEL; // 0x42004C14 - __IO PTC_REG_YSELECTL_Type YENABLEH; // 0x42004C15 - __IO PTC_REG_XSELECTL_Type XENABLEL; // 0x42004C16 - __IO PTC_REG_XSELECTL_Type XENABLEH; // 0x42004C17 - - __IO PTC_REG_COMPCAPL_Type COMPCAPL; // 0x42004C18 - __IO PTC_REG_COMPCAPH_Type COMPCAPH; // 0x42004C19 - __IO PTC_REG_INTCAP_Type INTCAP; // 0x42004C1A - __IO PTC_REG_SERRES_Type SERRES; // 0x42004C1B - - __IO PTC_REG_CONVRESULT_Type RESULT; // 0x42004C1C + 0x42004C1D - uint8_t __pad4c1e__; // 0x42004C1E unknown - uint8_t __pad4c1f__; // 0x42004C1F unknown - __IO PTC_REG_BURSTMODE_Type BURSTMODE; // 0x42004C20 -} Ptc; - -#define PTC (( Ptc *)0x42004C00U) - -#define PTC_REG_INTDISABLE 0x42004C08 -#define PTC_REG_INTENABLE 0x42004C09 -#define PTC_BIT_EOCINTEN 0x01 -#define PTC_BIT_WCOINTEN 0x02 - -#define PTC_REG_INTFLAGS 0x42004C0A - -#endif // ADAFRUIT_FREETOUCH_PTC_COMPONENT_H diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index 032bd164f..c66f0d0b3 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -46,6 +46,7 @@ #define MICROPY_PY_BUILTINS_SLICE (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) +#define MICROPY_NONSTANDARD_TYPECODES (0) #define MICROPY_PY_BUILTINS_PROPERTY (1) #define MICROPY_PY_BUILTINS_MIN_MAX (1) #define MICROPY_PY___FILE__ (1) @@ -63,6 +64,7 @@ #define MICROPY_PY_SYS (1) #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) +#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) #define MICROPY_STREAMS_NON_BLOCK (1) // fatfs configuration used in ffconf.h diff --git a/ports/atmel-samd/peripherals.h b/ports/atmel-samd/peripherals.h index bb01bc1ac..18c7f44d5 100644 --- a/ports/atmel-samd/peripherals.h +++ b/ports/atmel-samd/peripherals.h @@ -35,6 +35,8 @@ 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); +Sercom* sercom_insts[SERCOM_INST_NUM]; + #ifdef SAMD21 #include "samd21_peripherals.h" #endif diff --git a/ports/atmel-samd/samd21_peripherals.c b/ports/atmel-samd/samd21_peripherals.c index 484c787cb..a27e49e0e 100644 --- a/ports/atmel-samd/samd21_peripherals.c +++ b/ports/atmel-samd/samd21_peripherals.c @@ -56,7 +56,8 @@ static const uint8_t SERCOMx_GCLK_ID_SLOW[] = { #endif }; - +Sercom* sercom_insts[SERCOM_INST_NUM] = SERCOM_INSTS; + // Clock initialization as done in Atmel START. void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index) { _pm_enable_bus_clock(PM_BUS_APBC, sercom); diff --git a/ports/atmel-samd/samd21_pins.c b/ports/atmel-samd/samd21_pins.c index f1d006de8..eafc4b5fb 100644 --- a/ports/atmel-samd/samd21_pins.c +++ b/ports/atmel-samd/samd21_pins.c @@ -30,15 +30,13 @@ #define SERCOM(sercom_index, p_pad) \ { \ - .sercom = SERCOM## sercom_index, \ .index = sercom_index, \ .pad = p_pad \ } #define NO_SERCOM \ { \ - .sercom = 0, \ - .index = 0, \ + .index = 0x3f, \ .pad = 0 \ } @@ -57,7 +55,7 @@ .wave_output = p_wave_output \ } -#define NO_TIMER TCC(0, 0) +#define NO_TIMER TCC(0xff, 0) #define TOUCH(y_line) \ .has_touch = true, \ @@ -92,8 +90,6 @@ const mcu_pin_obj_t pin_## p_name = { \ .sercom = {p_primary_sercom, p_secondary_sercom}, \ } -#define NO_ADC_INPUT (0) - // 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. diff --git a/ports/atmel-samd/samd51_peripherals.c b/ports/atmel-samd/samd51_peripherals.c index e06f7f9df..8f37bdfd1 100644 --- a/ports/atmel-samd/samd51_peripherals.c +++ b/ports/atmel-samd/samd51_peripherals.c @@ -60,7 +60,8 @@ static const uint8_t SERCOMx_GCLK_ID_SLOW[] = { #endif }; - +Sercom* sercom_insts[SERCOM_INST_NUM] = SERCOM_INSTS; + // Clock initialization as done in Atmel START. void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index) { hri_gclk_write_PCHCTRL_reg(GCLK, diff --git a/ports/atmel-samd/samd51_pins.c b/ports/atmel-samd/samd51_pins.c index 78bdf0553..6d597b6e1 100644 --- a/ports/atmel-samd/samd51_pins.c +++ b/ports/atmel-samd/samd51_pins.c @@ -30,15 +30,13 @@ #define SERCOM(sercom_index, p_pad) \ { \ - .sercom = SERCOM## sercom_index, \ .index = sercom_index, \ .pad = p_pad \ } #define NO_SERCOM \ { \ - .sercom = 0, \ - .index = 0, \ + .index = 0x3f, \ .pad = 0 \ } @@ -91,8 +89,6 @@ const mcu_pin_obj_t pin_## p_name = { \ .sercom = {p_primary_sercom, p_secondary_sercom}, \ } -#define NO_ADC_INPUT (0) - // 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. @@ -1139,7 +1135,7 @@ PIN(PA31, EXTINT_CHANNEL(15), NO_ADC, NO_ADC, NO_TOUCH, #else NO_SERCOM, #endif - SERCOM(1, 23), + SERCOM(1, 3), #ifdef TC6 TC(6, 1), #else diff --git a/ports/atmel-samd/supervisor/filesystem.c b/ports/atmel-samd/supervisor/filesystem.c index 45dc5667b..bff78a41c 100644 --- a/ports/atmel-samd/supervisor/filesystem.c +++ b/ports/atmel-samd/supervisor/filesystem.c @@ -42,6 +42,12 @@ fs_user_mount_t fs_user_mount_flash; mp_vfs_mount_t mp_vfs_mount_flash; +static void make_empty_file(FATFS *fatfs, const char *path) { + FIL fp; + f_open(fatfs, &fp, path, FA_WRITE | FA_CREATE_ALWAYS); + f_close(&fp); +} + // we don't make this function static because it needs a lot of stack and we // want it to be executed without using stack within main() function void filesystem_init(bool create_allowed) { @@ -65,6 +71,14 @@ void filesystem_init(bool create_allowed) { // set label f_setlabel(&vfs_fat->fatfs, "CIRCUITPY"); + + // inhibit file indexing on MacOS + f_mkdir(&vfs_fat->fatfs, "/.fseventsd"); + make_empty_file(&vfs_fat->fatfs, "/.metadata_never_index"); + make_empty_file(&vfs_fat->fatfs, "/.Trashes"); + make_empty_file(&vfs_fat->fatfs, "/.fseventsd/no_log"); + + // and ensure everything is flushed flash_flush(); } else if (res != FR_OK) { return; diff --git a/ports/atmel-samd/usb.c b/ports/atmel-samd/usb.c index f8df04b74..7fff957c0 100644 --- a/ports/atmel-samd/usb.c +++ b/ports/atmel-samd/usb.c @@ -102,12 +102,13 @@ static void init_hardware(void) { #endif } -COMPILER_ALIGNED(4) uint8_t cdc_packet_buffer[64]; +#define CDC_BULKOUT_SIZE CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKOUT_MAXPKSZ +COMPILER_ALIGNED(4) uint8_t cdc_packet_buffer[CDC_BULKOUT_SIZE]; static volatile bool pending_read; static int32_t start_read(void) { pending_read = true; - int32_t result = cdcdf_acm_read(cdc_packet_buffer, 64); + int32_t result = cdcdf_acm_read(cdc_packet_buffer, CDC_BULKOUT_SIZE); if (result != ERR_NONE) { pending_read = false; } @@ -151,14 +152,6 @@ static bool read_complete(const uint8_t ep, const enum usb_xfer_code rc, const u } atomic_leave_critical(&flags); - // Trigger a follow up read if we have space. - if (usb_rx_count < USB_RX_BUF_SIZE) { - int32_t result = start_read(); - if (result != ERR_NONE) { - return true; - } - } - /* No error. */ return false; } @@ -170,7 +163,9 @@ static bool write_complete(const uint8_t ep, return false; // No errors. } // This is called after writes are finished. + usb_transmitting = false; + /* No error. */ return false; } @@ -228,25 +223,32 @@ void init_usb(void) { } static bool cdc_enabled(void) { - if (mp_cdc_enabled) { - return true; - } if (!cdcdf_acm_is_enabled()) { + mp_cdc_enabled = false; return false; } - cdcdf_acm_register_callback(CDCDF_ACM_CB_READ, (FUNC_PTR)read_complete); - cdcdf_acm_register_callback(CDCDF_ACM_CB_WRITE, (FUNC_PTR)write_complete); - cdcdf_acm_register_callback(CDCDF_ACM_CB_STATE_C, (FUNC_PTR)usb_device_cb_state_c); - cdcdf_acm_register_callback(CDCDF_ACM_CB_LINE_CODING_C, (FUNC_PTR)usb_device_cb_line_coding_c); - mp_cdc_enabled = true; + if (!mp_cdc_enabled) { + cdcdf_acm_register_callback(CDCDF_ACM_CB_READ, (FUNC_PTR)read_complete); + cdcdf_acm_register_callback(CDCDF_ACM_CB_WRITE, (FUNC_PTR)write_complete); + cdcdf_acm_register_callback(CDCDF_ACM_CB_STATE_C, (FUNC_PTR)usb_device_cb_state_c); + cdcdf_acm_register_callback(CDCDF_ACM_CB_LINE_CODING_C, (FUNC_PTR)usb_device_cb_line_coding_c); + mp_cdc_enabled = true; + } return true; } bool usb_bytes_available(void) { + // Check if the buffer has data, but not enough + // space to hold another read. + if (usb_rx_count > USB_RX_BUF_SIZE - CDC_BULKOUT_SIZE) { + return true; + } + // Buffer has enough room if (cdc_enabled() && !pending_read) { start_read(); } + // Buffer is empty and/or no new data is available if (usb_rx_count == 0) { return false; } @@ -264,16 +266,11 @@ int usb_read(void) { data = usb_rx_buf[usb_rx_buf_head]; usb_rx_buf_head++; usb_rx_count--; - if ((USB_RX_BUF_SIZE) == usb_rx_buf_head) { + if (usb_rx_buf_head == USB_RX_BUF_SIZE) { usb_rx_buf_head = 0; } CRITICAL_SECTION_LEAVE(); - // Trigger a new read because we just cleared some space. - if (!pending_read && usb_rx_count == USB_RX_BUF_SIZE - 1) { - start_read(); - } - return data; } @@ -320,9 +317,10 @@ bool usb_connected(void) { // Poll for input if keyboard interrupts are enabled, // so that we can check for the interrupt char. read_complete() does the checking. +// also make sure we have enough room in the local buffer void usb_cdc_background() { // - if (mp_interrupt_char != -1 && cdc_enabled() && !pending_read) { + if (mp_interrupt_char != -1 && cdc_enabled() && !pending_read && (usb_rx_count < USB_RX_BUF_SIZE - CDC_BULKOUT_SIZE)) { start_read(); } } diff --git a/ports/atmel-samd/usb_mass_storage.c b/ports/atmel-samd/usb_mass_storage.c index 818736a78..9b6715158 100644 --- a/ports/atmel-samd/usb_mass_storage.c +++ b/ports/atmel-samd/usb_mass_storage.c @@ -260,6 +260,9 @@ int32_t usb_msc_xfer_done(uint8_t lun) { if (active_read) { active_addr += 1; active_nblocks--; + if (active_nblocks == 0) { + active_read = false; + } } if (active_write) { @@ -277,11 +280,14 @@ int32_t usb_msc_xfer_done(uint8_t lun) { // drive into our cache and trigger the USB DMA to output the // sector. Once the sector is transmitted, xfer_done will be called. void usb_msc_background(void) { - if (active_read && !usb_busy) { - if (active_nblocks == 0) { - active_read = false; - return; - } + // Check USB busy first because we never want to queue another transfer if it is. Checking + // active_read or active_write first leaves the possibility that they are true, an xfer done + // interrupt occurs (setting them false), turning off usb_busy and causing us to queue a + // spurious transfer. + if (usb_busy) { + return; + } + if (active_read) { fs_user_mount_t * vfs = get_vfs(active_lun); disk_read(vfs, sector_buffer, active_addr, 1); CRITICAL_SECTION_ENTER(); @@ -289,7 +295,7 @@ void usb_msc_background(void) { usb_busy = result == ERR_NONE; CRITICAL_SECTION_LEAVE(); } - if (active_write && !usb_busy) { + if (active_write) { if (sector_loaded) { fs_user_mount_t * vfs = get_vfs(active_lun); disk_write(vfs, sector_buffer, active_addr, 1); diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index cdf06450c..616e9875c 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -49,6 +49,7 @@ #define MICROPY_PY_GC (1) #define MICROPY_PY_ARRAY (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) +#define MICROPY_NONSTANDARD_TYPECODES (0) #define MICROPY_PY_COLLECTIONS (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_MATH (0) @@ -90,6 +91,7 @@ #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) +#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) #define MICROPY_WARNINGS (1) #define MICROPY_PY_STR_BYTES_CMP_WARN (1) diff --git a/ports/nrf/common-hal/microcontroller/Processor.c b/ports/nrf/common-hal/microcontroller/Processor.c index cf808cdf4..0cceb6a66 100644 --- a/ports/nrf/common-hal/microcontroller/Processor.c +++ b/ports/nrf/common-hal/microcontroller/Processor.c @@ -76,7 +76,7 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { for (int i=0; i<2; i++) { for (int k=0; k<4; k++) { - raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xf; + raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xff; } } } diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 053a3bbab..45c82439b 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -47,6 +47,7 @@ //CP UPDATE: See mpconfigport.h for LONGINT implementation #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) +#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) #define MICROPY_OPT_COMPUTED_GOTO (0) #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0) @@ -99,6 +100,7 @@ #define MICROPY_PY_ALL_SPECIAL_METHODS (0) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (0) +#define MICROPY_NONSTANDARD_TYPECODES (0) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (0) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_MAXSIZE (1) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 5bdcf4e1a..dacf68019 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -189,7 +189,7 @@ include $(TOP)/py/mkrules.mk test: $(PROG) $(TOP)/tests/run-tests $(eval DIRNAME=ports/$(notdir $(CURDIR))) - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests --auto-jobs # install micropython in /usr/local/bin TARGET = micropython @@ -254,10 +254,10 @@ coverage: coverage_test: coverage $(eval DIRNAME=ports/$(notdir $(CURDIR))) - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests -d thread - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --emit native - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --via-mpy -d basics float + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --auto-jobs + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --auto-jobs -d thread + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --auto-jobs --emit native + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests -j1 --via-mpy -d basics float gcov -o build-coverage/py $(TOP)/py/*.c gcov -o build-coverage/extmod $(TOP)/extmod/*.c diff --git a/ports/unix/mpconfigport_coverage.h b/ports/unix/mpconfigport_coverage.h index 367b4853a..86d95eb39 100644 --- a/ports/unix/mpconfigport_coverage.h +++ b/ports/unix/mpconfigport_coverage.h @@ -43,4 +43,5 @@ #define MICROPY_PY_IO_BUFFEREDWRITER (1) #undef MICROPY_VFS_FAT #define MICROPY_VFS_FAT (1) +#define MICROPY_FATFS_USE_LABEL (1) #define MICROPY_PY_FRAMEBUF (1) diff --git a/ports/windows/.appveyor.yml b/ports/windows/.appveyor.yml deleted file mode 100644 index a82cf5adc..000000000 --- a/ports/windows/.appveyor.yml +++ /dev/null @@ -1,32 +0,0 @@ -environment: - # Python version used - MICROPY_CPYTHON3: c:/python34/python.exe - -init: - # Set build version number to commit to be travis-like -- ps: Update-AppveyorBuild -Version $env:appveyor_repo_commit.substring(0,8) - -configuration: -- Debug -- Release - -platform: -- x86 -- x64 - -build: - project: ports/windows/micropython.vcxproj - verbosity: normal - -test_script: -- cmd: >- - cd tests - - %MICROPY_CPYTHON3% run-tests - -skip_tags: true - -deploy: off - -nuget: - disable_publish_on_pr: true @@ -190,6 +190,13 @@ void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw for (size_t i = 0; i < n_kw; i++) { // the keys in kwargs are expected to be qstr objects mp_obj_t wanted_arg_name = kwargs[2 * i]; + if(MP_UNLIKELY(!MP_OBJ_IS_QSTR(wanted_arg_name))) { + #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE + mp_raise_TypeError("unexpected keyword argument"); + #else + mp_raise_TypeError("keywords must be strings"); + #endif + } for (size_t j = 0; j < n_pos_args + n_kwonly_args; j++) { if (wanted_arg_name == arg_names[j]) { if (code_state->state[n_state - 1 - j] != MP_OBJ_NULL) { diff --git a/py/binary.c b/py/binary.c index 62cb384f1..bb334ed3d 100644 --- a/py/binary.c +++ b/py/binary.c @@ -57,8 +57,10 @@ size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign) { size = 4; break; case 'q': case 'Q': size = 8; break; +#if MICROPY_NONSTANDARD_TYPECODES case 'P': case 'O': case 'S': size = sizeof(void*); break; +#endif case 'f': size = sizeof(float); break; case 'd': @@ -89,9 +91,11 @@ size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign) { case 'q': case 'Q': align = alignof(long long); size = sizeof(long long); break; +#if MICROPY_NONSTANDARD_TYPECODES case 'P': case 'O': case 'S': align = alignof(void*); size = sizeof(void*); break; +#endif case 'f': align = alignof(float); size = sizeof(float); break; @@ -148,12 +152,14 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index) { case 'd': return mp_obj_new_float(((double*)p)[index]); #endif +#if MICROPY_NONSTANDARD_TYPECODES // Extension to CPython: array of objects case 'O': return ((mp_obj_t*)p)[index]; // Extension to CPython: array of pointers case 'P': return mp_obj_new_int((mp_int_t)(uintptr_t)((void**)p)[index]); +#endif } return MP_OBJ_NEW_SMALL_INT(val); } @@ -202,11 +208,13 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) { long long val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p); - if (val_type == 'O') { + if (MICROPY_NONSTANDARD_TYPECODES && (val_type == 'O')) { return (mp_obj_t)(mp_uint_t)val; +#if MICROPY_NONSTANDARD_TYPECODES } else if (val_type == 'S') { const char *s_val = (const char*)(uintptr_t)(mp_uint_t)val; return mp_obj_new_str(s_val, strlen(s_val), false); +#endif #if MICROPY_PY_BUILTINS_FLOAT } else if (val_type == 'f') { union { uint32_t i; float f; } fpu = {val}; @@ -267,9 +275,11 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte ** mp_uint_t val; switch (val_type) { +#if MICROPY_NONSTANDARD_TYPECODES case 'O': val = (mp_uint_t)val_in; break; +#endif #if MICROPY_PY_BUILTINS_FLOAT case 'f': { union { uint32_t i; float f; } fp_sp; @@ -324,10 +334,12 @@ void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t v ((double*)p)[index] = mp_obj_get_float(val_in); break; #endif +#if MICROPY_NONSTANDARD_TYPECODES // Extension to CPython: array of objects case 'O': ((mp_obj_t*)p)[index] = val_in; break; +#endif default: #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE if (MP_OBJ_IS_TYPE(val_in, &mp_type_int)) { @@ -384,9 +396,11 @@ void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, m ((double*)p)[index] = val; break; #endif +#if MICROPY_NONSTANDARD_TYPECODES // Extension to CPython: array of pointers case 'P': ((void**)p)[index] = (void*)(uintptr_t)val; break; +#endif } } diff --git a/py/gc_long_lived.c b/py/gc_long_lived.c index c50bbcd83..d34fde5d9 100644 --- a/py/gc_long_lived.c +++ b/py/gc_long_lived.c @@ -78,9 +78,9 @@ mp_obj_property_t *make_property_long_lived(mp_obj_property_t *prop, uint8_t max if (max_depth == 0) { return prop; } - prop->proxy[0] = make_fun_bc_long_lived((mp_obj_fun_bc_t*) prop->proxy[0], max_depth - 1); - prop->proxy[1] = make_fun_bc_long_lived((mp_obj_fun_bc_t*) prop->proxy[1], max_depth - 1); - prop->proxy[2] = make_fun_bc_long_lived((mp_obj_fun_bc_t*) prop->proxy[2], max_depth - 1); + prop->proxy[0] = make_obj_long_lived((mp_obj_fun_bc_t*) prop->proxy[0], max_depth - 1); + prop->proxy[1] = make_obj_long_lived((mp_obj_fun_bc_t*) prop->proxy[1], max_depth - 1); + prop->proxy[2] = make_obj_long_lived((mp_obj_fun_bc_t*) prop->proxy[2], max_depth - 1); return gc_make_long_lived(prop); } diff --git a/py/mpconfig.h b/py/mpconfig.h index 252ab7f37..765ae1e8f 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -888,6 +888,12 @@ typedef double mp_float_t; #define MICROPY_PY_ARRAY_SLICE_ASSIGN (0) #endif +// Whether to support nonstandard typecodes "O", "P" and "S" +// in array and struct modules. +#ifndef MICROPY_NONSTANDARD_TYPECODES +#define MICROPY_NONSTANDARD_TYPECODES (1) +#endif + // Whether to support attrtuple type (MicroPython extension) // It provides space-efficient tuples with attribute access #ifndef MICROPY_PY_ATTRTUPLE diff --git a/py/objarray.c b/py/objarray.c index a1a979b56..c4c547e19 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -241,6 +241,39 @@ STATIC mp_obj_t array_unary_op(mp_unary_op_t op, mp_obj_t o_in) { STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_array_t *lhs = MP_OBJ_TO_PTR(lhs_in); switch (op) { + case MP_BINARY_OP_MULTIPLY: + case MP_BINARY_OP_INPLACE_MULTIPLY: { + if (!MP_OBJ_IS_INT(rhs_in)) { + return MP_OBJ_NULL; // op not supported + } + mp_uint_t repeat = mp_obj_get_int(rhs_in); + bool inplace = (op == MP_BINARY_OP_INPLACE_MULTIPLY); + mp_buffer_info_t lhs_bufinfo; + array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ); + mp_obj_array_t *res; + byte *ptr; + size_t orig_lhs_bufinfo_len = lhs_bufinfo.len; + if(inplace) { + res = lhs; + size_t item_sz = mp_binary_get_size('@', lhs->typecode, NULL); + lhs->items = m_renew(byte, lhs->items, (lhs->len + lhs->free) * item_sz, lhs->len * repeat * item_sz); + lhs->len = lhs->len * repeat; + lhs->free = 0; + if (!repeat) + return MP_OBJ_FROM_PTR(res); + repeat--; + ptr = (byte*)res->items + orig_lhs_bufinfo_len; + } else { + res = array_new(lhs_bufinfo.typecode, lhs->len * repeat); + ptr = (byte*)res->items; + } + if(orig_lhs_bufinfo_len) { + for(;repeat--; ptr += orig_lhs_bufinfo_len) { + memcpy(ptr, lhs_bufinfo.buf, orig_lhs_bufinfo_len); + } + } + return MP_OBJ_FROM_PTR(res); + } case MP_BINARY_OP_ADD: { // allow to add anything that has the buffer protocol (extension to CPython) mp_buffer_info_t lhs_bufinfo; @@ -437,9 +470,11 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value } else { mp_seq_replace_slice_no_grow(dest_items, o->len, slice.start, slice.stop, src_items, src_len, item_sz); +#if MICROPY_NONSTANDARD_TYPECODES // Clear "freed" elements at the end of list // TODO: This is actually only needed for typecode=='O' mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz); +#endif // TODO: alloc policy after shrinking } o->len += len_adj; diff --git a/py/objgenerator.c b/py/objgenerator.c index 139452442..ff566c076 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -32,6 +32,7 @@ #include "py/bc.h" #include "py/objgenerator.h" #include "py/objfun.h" +#include "py/stackctrl.h" /******************************************************************************/ /* generator wrapper */ @@ -92,6 +93,7 @@ STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_pri } mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) { + MP_STACK_CHECK(); mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance)); mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); if (self->code_state.ip == 0) { diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 7b5cb0b9d..808fae6e4 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -343,6 +343,10 @@ mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent, mp_obj_t modulus) { mpz_t *rhs = mp_mpz_for_int(exponent, &r_temp); mpz_t *mod = mp_mpz_for_int(modulus, &m_temp); + if (mpz_is_zero(mod)) { + mp_raise_msg(&mp_type_ValueError, "pow() 3rd argument cannot be 0"); + } + mpz_pow3_inpl(&(res_p->mpz), lhs, rhs, mod); if (lhs == &l_temp) { mpz_deinit(lhs); } diff --git a/py/objstr.c b/py/objstr.c index 64306f54f..7ace1cf73 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -692,8 +692,13 @@ STATIC mp_obj_t str_finder(size_t n_args, const mp_obj_t *args, int direction, b end = str_index_to_ptr(self_type, haystack, haystack_len, args[3], true); } + if (end < start) { + goto out_error; + } + const byte *p = find_subbytes(start, end - start, needle, needle_len, direction); if (p == NULL) { + out_error: // not found if (is_index) { mp_raise_ValueError("substring not found"); diff --git a/py/objtype.c b/py/objtype.c index 1d6dc0b6c..5b70e8e48 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -567,6 +567,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des mp_obj_class_lookup(&lookup, self->base.type); mp_obj_t member = dest[0]; if (member != MP_OBJ_NULL) { + // changes here may may require changes to super_attr, below #if MICROPY_PY_BUILTINS_PROPERTY if (MP_OBJ_IS_TYPE(member, &mp_type_property)) { // object member is a property; delegate the load to the property @@ -980,8 +981,14 @@ const mp_obj_type_t mp_type_type = { }; mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) { - assert(MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)); // MicroPython restriction, for now - assert(MP_OBJ_IS_TYPE(locals_dict, &mp_type_dict)); // MicroPython restriction, for now + if(!MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)) { + // MicroPython restriction, for now + mp_raise_TypeError("type() argument 2 must be tuple"); + } + if(!MP_OBJ_IS_TYPE(locals_dict, &mp_type_dict)) { + // MicroPython restriction, for now + mp_raise_TypeError("type() argument 3 must be dict"); + } // TODO might need to make a copy of locals_dict; at least that's how CPython does it @@ -990,7 +997,9 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) mp_obj_t *items; mp_obj_tuple_get(bases_tuple, &len, &items); for (size_t i = 0; i < len; i++) { - assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type)); + if(!MP_OBJ_IS_TYPE(items[i], &mp_type_type)) { + mp_raise_TypeError("type is not an acceptable base type"); + } mp_obj_type_t *t = MP_OBJ_TO_PTR(items[i]); // TODO: Verify with CPy, tested on function type if (t->make_new == NULL) { @@ -1076,6 +1085,9 @@ STATIC mp_obj_t super_make_new(const mp_obj_type_t *type_in, size_t n_args, size // 0 arguments are turned into 2 in the compiler // 1 argument is not yet implemented mp_arg_check_num(n_args, n_kw, 2, 2, false); + if(!MP_OBJ_IS_TYPE(args[0], &mp_type_type)) { + mp_raise_TypeError("first argument to super() must be type"); + } mp_obj_super_t *o = m_new_obj(mp_obj_super_t); *o = (mp_obj_super_t){{type_in}, args[0], args[1]}; return MP_OBJ_FROM_PTR(o); @@ -1112,14 +1124,37 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type)); mp_obj_class_lookup(&lookup, (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i])); if (dest[0] != MP_OBJ_NULL) { - return; + break; } } } else { mp_obj_class_lookup(&lookup, type->parent); - if (dest[0] != MP_OBJ_NULL) { - return; + } + + if (dest[0] != MP_OBJ_NULL) { + mp_obj_t member = dest[0]; + // changes to mp_obj_instance_load_attr may require changes + // here... + #if MICROPY_PY_BUILTINS_PROPERTY + if (MP_OBJ_IS_TYPE(member, &mp_type_property)) { + const mp_obj_t *proxy = mp_obj_property_get(member); + if (proxy[0] == mp_const_none) { + mp_raise_AttributeError("unreadable attribute"); + } else { + dest[0] = mp_call_function_n_kw(proxy[0], 1, 0, &self_in); + } + } + #endif + #if MICROPY_PY_DESCRIPTORS + mp_obj_t attr_get_method[4]; + mp_load_method_maybe(member, MP_QSTR___get__, attr_get_method); + if (attr_get_method[0] != MP_OBJ_NULL) { + attr_get_method[2] = self_in; + attr_get_method[3] = MP_OBJ_FROM_PTR(mp_obj_get_type(self_in)); + dest[0] = mp_call_method_n_kw(2, 0, attr_get_method); } + #endif + return; } mp_obj_class_lookup(&lookup, &mp_type_object); diff --git a/shared-bindings/gamepad/GamePad.c b/shared-bindings/gamepad/GamePad.c index a03b9318d..d80d1fcf6 100644 --- a/shared-bindings/gamepad/GamePad.c +++ b/shared-bindings/gamepad/GamePad.c @@ -27,6 +27,7 @@ #include "py/runtime.h" #include "py/mphal.h" #include "shared-module/gamepad/GamePad.h" +#include "shared-bindings/digitalio/DigitalInOut.h" #include "GamePad.h" @@ -96,6 +97,12 @@ STATIC mp_obj_t gamepad_make_new(const mp_obj_type_t *type, size_t n_args, gamepad_singleton = m_new_obj(gamepad_obj_t); gamepad_singleton->base.type = &gamepad_type; } + 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)); + } + } gamepad_init(n_args, args); return MP_OBJ_FROM_PTR(gamepad_singleton); } diff --git a/shared-bindings/help.c b/shared-bindings/help.c index cdd9a4a93..d8ffc13dd 100644 --- a/shared-bindings/help.c +++ b/shared-bindings/help.c @@ -35,7 +35,7 @@ //| prints general port information. //| -const char *circuitpython_help_text = +const char circuitpython_help_text[] = "Welcome to Adafruit CircuitPython " MICROPY_GIT_TAG "!\r\n" "\r\n" "Please visit learn.adafruit.com/category/circuitpython for project guides.\r\n" diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c index 6f6a30da6..734cabcc1 100644 --- a/shared-bindings/storage/__init__.c +++ b/shared-bindings/storage/__init__.c @@ -122,12 +122,22 @@ mp_obj_t storage_remount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a } MP_DEFINE_CONST_FUN_OBJ_KW(storage_remount_obj, 1, storage_remount); +//| .. function:: getmount(mount_path) +//| +//| Retrieves the mount object associated with the mount path +//| +mp_obj_t storage_getmount(const mp_obj_t mnt_in) { + return common_hal_storage_getmount(mp_obj_str_get_str(mnt_in)); +} +MP_DEFINE_CONST_FUN_OBJ_1(storage_getmount_obj, storage_getmount); + STATIC const mp_rom_map_elem_t storage_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_storage) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&storage_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&storage_umount_obj) }, { MP_ROM_QSTR(MP_QSTR_remount), MP_ROM_PTR(&storage_remount_obj) }, + { MP_ROM_QSTR(MP_QSTR_getmount), MP_ROM_PTR(&storage_getmount_obj) }, //| .. class:: VfsFat(block_device) //| @@ -135,6 +145,49 @@ STATIC const mp_rom_map_elem_t storage_module_globals_table[] = { //| //| :param block_device: Block device the the filesystem lives on //| + //| .. attribute:: label + //| + //| The filesystem label, up to 11 case-insensitive bytes. Note that + //| this property can only be set when the device is writable by the + //| microcontroller. + //| + //| .. method:: mkfs + //| + //| Format the block device, deleting any data that may have been there + //| + //| .. method:: open(path, mode) + //| + //| Like builtin ``open()`` + //| + //| .. method:: ilistdir([path]) + //| + //| Return an iterator whose values describe files and folders within + //| ``path`` + //| + //| .. method:: mkdir(path) + //| + //| Like `os.mkdir` + //| + //| .. method:: rmdir(path) + //| + //| Like `os.rmdir` + //| + //| .. method:: stat(path) + //| + //| Like `os.stat` + //| + //| .. method:: statvfs(path) + //| + //| Like `os.statvfs` + //| + //| .. method:: mount(readonly, mkfs) + //| + //| Don't call this directly, call `storage.mount`. + //| + //| .. method:: umount + //| + //| Don't call this directly, call `storage.umount`. + //| { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, }; diff --git a/shared-bindings/storage/__init__.h b/shared-bindings/storage/__init__.h index 574b5ff8d..76b9ae854 100644 --- a/shared-bindings/storage/__init__.h +++ b/shared-bindings/storage/__init__.h @@ -34,5 +34,6 @@ void common_hal_storage_mount(mp_obj_t vfs_obj, const char* path, bool readonly) void common_hal_storage_umount_path(const char* path); void common_hal_storage_umount_object(mp_obj_t vfs_obj); void common_hal_storage_remount(const char* path, bool readonly); +mp_obj_t common_hal_storage_getmount(const char* path); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_STORAGE___INIT___H diff --git a/shared-module/gamepad/GamePad.c b/shared-module/gamepad/GamePad.c index 3a2b8a3fe..cd1df9b57 100644 --- a/shared-module/gamepad/GamePad.c +++ b/shared-module/gamepad/GamePad.c @@ -31,6 +31,7 @@ #include "shared-bindings/digitalio/Pull.h" #include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/util.h" void gamepad_init(size_t n_pins, const mp_obj_t* pins) { @@ -39,8 +40,13 @@ void gamepad_init(size_t n_pins, const mp_obj_t* pins) { } 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) { + common_hal_digitalio_digitalinout_switch_to_input(pin, PULL_UP); + } gamepad_singleton->pins[i] = pin; - common_hal_digitalio_digitalinout_switch_to_input(pin, PULL_UP); } gamepad_singleton->last = 0; } diff --git a/shared-module/gamepad/__init__.c b/shared-module/gamepad/__init__.c index b6c8be215..591a2fa0a 100644 --- a/shared-module/gamepad/__init__.c +++ b/shared-module/gamepad/__init__.c @@ -42,8 +42,10 @@ void gamepad_tick(void) { if (!pin) { break; } - if (!common_hal_digitalio_digitalinout_get_value(pin)) { - gamepad_current |= 1<<i; + 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; } } gamepad_singleton->pressed |= gamepad_singleton->last & gamepad_current; diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index 97a049bac..5b0bbe01e 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -109,19 +109,19 @@ void common_hal_storage_umount_object(mp_obj_t vfs_obj) { mp_vfs_proxy_call(vfs, MP_QSTR_umount, 0, NULL); } -void common_hal_storage_umount_path(const char* mount_path) { - // remove vfs from the mount table - mp_obj_t *vfs_obj = NULL; +STATIC mp_obj_t storage_object_from_path(const char* mount_path) { for (mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table); *vfsp != NULL; vfsp = &(*vfsp)->next) { if (strcmp(mount_path, (*vfsp)->str) == 0) { - vfs_obj = (*vfsp)->obj; - break; + return (*vfsp)->obj; } } + mp_raise_OSError(MP_EINVAL); +} - if (vfs_obj == NULL) { - mp_raise_OSError(MP_EINVAL); - } +void common_hal_storage_umount_path(const char* mount_path) { + common_hal_storage_umount_object(storage_object_from_path(mount_path)); +} - common_hal_storage_umount_object(vfs_obj); +mp_obj_t common_hal_storage_getmount(const char *mount_path) { + return storage_object_from_path(mount_path); } diff --git a/shared-module/struct/__init__.c b/shared-module/struct/__init__.c index e944f7738..eac41c9c3 100644 --- a/shared-module/struct/__init__.c +++ b/shared-module/struct/__init__.c @@ -33,9 +33,11 @@ #include "py/parsenum.h" void struct_validate_format(char fmt) { +#if MICROPY_NONSTANDARD_TYPECODES if( fmt == 'S' || fmt == 'O') { mp_raise_RuntimeError("'S' and 'O' are not supported format types"); } +#endif } char get_fmt_type(const char **fmt) { diff --git a/tests/basics/array_micropython.py b/tests/basics/array_micropython.py index e26ad7ae9..b92c5a9b9 100644 --- a/tests/basics/array_micropython.py +++ b/tests/basics/array_micropython.py @@ -5,6 +5,12 @@ except ImportError: print("SKIP") raise SystemExit +try: + array.array('O') +except ValueError: + print("SKIP") + raise SystemExit + # arrays of objects a = array.array('O') a.append(1) diff --git a/tests/basics/array_mul.py b/tests/basics/array_mul.py new file mode 100644 index 000000000..bb5f3aa6b --- /dev/null +++ b/tests/basics/array_mul.py @@ -0,0 +1,28 @@ +try: + import array +except ImportError: + print("SKIP") + raise SystemExit + +a1 = array.array('I', [1]) +a2 = array.array('I', [2]) * 2 +a3 = (a1 + a2) +print(a3) + +a3 *= 5 +print(a3) + +a3 *= 0 +print(a3) + +a4 = a2 * 0 +print(a4) + +a4 *= 0 +print(a4) + +a4 = a4 * 2 +print(a4) + +a4 *= 2 +print(a4) diff --git a/tests/basics/builtin_pow3.py b/tests/basics/builtin_pow3.py index 69b57e548..293a5acc9 100644 --- a/tests/basics/builtin_pow3.py +++ b/tests/basics/builtin_pow3.py @@ -22,3 +22,8 @@ try: print(pow(4, 5, "z")) except TypeError: print("TypeError expected") + +try: + print(pow(4, 5, 0)) +except ValueError: + print("ValueError expected") diff --git a/tests/basics/class_super.py b/tests/basics/class_super.py index 1338ef452..5a18017ac 100644 --- a/tests/basics/class_super.py +++ b/tests/basics/class_super.py @@ -34,3 +34,10 @@ class B(A): print(super().bar) # accessing attribute after super() return super().foo().count(2) # calling a subsequent method print(B().foo()) + +try: + super(1, 1).x +except TypeError: + print(True) +else: + print(False) diff --git a/tests/cpydiff/core_class_superproperty.py b/tests/basics/core_class_superproperty.py index 1ec210550..69db10046 100644 --- a/tests/cpydiff/core_class_superproperty.py +++ b/tests/basics/core_class_superproperty.py @@ -1,8 +1,5 @@ """ -categories: Core,Classes -description: Calling super() getter property in subclass will return a property object, not the value -cause: Unknown -workaround: Unknown +test that calling super() getter property in subclass will return the value """ class A: @property diff --git a/tests/basics/fun_calldblstar.py b/tests/basics/fun_calldblstar.py index aae9828cf..15038b2f5 100644 --- a/tests/basics/fun_calldblstar.py +++ b/tests/basics/fun_calldblstar.py @@ -15,3 +15,10 @@ class A: a = A() a.f(1, **{'b':2}) a.f(1, **{'b':val for val in range(1)}) + +try: + f(1, **{len: 1}) +except TypeError: + print(True) +else: + print(False) diff --git a/tests/basics/gen_stack_overflow.py b/tests/basics/gen_stack_overflow.py new file mode 100644 index 000000000..5cba0e054 --- /dev/null +++ b/tests/basics/gen_stack_overflow.py @@ -0,0 +1,7 @@ +def gen(): + yield from gen() + +try: + print(list(gen())) +except RuntimeError: + print("RuntimeError") diff --git a/tests/basics/string_find.py b/tests/basics/string_find.py index 4a206eb0e..f9fcad3e5 100644 --- a/tests/basics/string_find.py +++ b/tests/basics/string_find.py @@ -21,6 +21,7 @@ print("0000".find('-1', 3)) print("0000".find('1', 3)) print("0000".find('1', 4)) print("0000".find('1', 5)) +print("aaaaaaaaaaa".find("bbb", 9, 2)) try: 'abc'.find(1) diff --git a/tests/basics/string_rfind.py b/tests/basics/string_rfind.py index 4d0e84018..54269d6f5 100644 --- a/tests/basics/string_rfind.py +++ b/tests/basics/string_rfind.py @@ -21,3 +21,4 @@ print("0000".rfind('-1', 3)) print("0000".rfind('1', 3)) print("0000".rfind('1', 4)) print("0000".rfind('1', 5)) +print("aaaaaaaaaaa".rfind("bbb", 9, 2)) diff --git a/tests/basics/struct_micropython.py b/tests/basics/struct_micropython.py index f203a4666..e72153071 100644 --- a/tests/basics/struct_micropython.py +++ b/tests/basics/struct_micropython.py @@ -9,6 +9,12 @@ except: print("SKIP") raise SystemExit +try: + struct.pack('O', None) +except ValueError: + print("SKIP") + raise SystemExit + class A(): pass diff --git a/tests/basics/types3.py b/tests/basics/types3.py new file mode 100644 index 000000000..71f790692 --- /dev/null +++ b/tests/basics/types3.py @@ -0,0 +1,20 @@ +try: + type('abc', None, None) +except TypeError: + print(True) +else: + print(False) + +try: + type('abc', (), None) +except TypeError: + print(True) +else: + print(False) + +try: + type('abc', (1,), {}) +except TypeError: + print(True) +else: + print(False) diff --git a/tests/extmod/vfs_fat_fileio1.py b/tests/extmod/vfs_fat_fileio1.py index d19df120b..8b9ff92eb 100644 --- a/tests/extmod/vfs_fat_fileio1.py +++ b/tests/extmod/vfs_fat_fileio1.py @@ -91,10 +91,8 @@ with open("foo_file.txt") as f2: f2.seek(0, 1) # SEEK_CUR print(f2.read(1)) - try: - f2.seek(1, 1) # SEEK_END - except OSError as e: - print(e.args[0] == uerrno.EOPNOTSUPP) + f2.seek(2, 1) # SEEK_CUR + print(f2.read(1)) f2.seek(-2, 2) # SEEK_END print(f2.read(1)) diff --git a/tests/extmod/vfs_fat_fileio1.py.exp b/tests/extmod/vfs_fat_fileio1.py.exp index d777585cf..a66f07605 100644 --- a/tests/extmod/vfs_fat_fileio1.py.exp +++ b/tests/extmod/vfs_fat_fileio1.py.exp @@ -7,7 +7,7 @@ hello!world! 12 h e -True +o d True [('foo_dir', 16384, 0)] diff --git a/tests/extmod/vfs_fat_ramdisk.py b/tests/extmod/vfs_fat_ramdisk.py index 801c69786..896641ab3 100644 --- a/tests/extmod/vfs_fat_ramdisk.py +++ b/tests/extmod/vfs_fat_ramdisk.py @@ -54,6 +54,8 @@ print(b"hello!" not in bdev.data) vfs = uos.VfsFat(bdev) uos.mount(vfs, "/ramdisk") +vfs.label = 'label test' +print("label:", vfs.label) print("statvfs:", vfs.statvfs("/ramdisk")) print("getcwd:", vfs.getcwd()) diff --git a/tests/extmod/vfs_fat_ramdisk.py.exp b/tests/extmod/vfs_fat_ramdisk.py.exp index ccd0f7134..a3c3470a9 100644 --- a/tests/extmod/vfs_fat_ramdisk.py.exp +++ b/tests/extmod/vfs_fat_ramdisk.py.exp @@ -1,5 +1,6 @@ True True +label: LABEL TEST statvfs: (512, 512, 16, 16, 16, 0, 0, 0, 0, 255) getcwd: / True diff --git a/tests/run-tests b/tests/run-tests index f1035c435..bcd2e5dcc 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -6,6 +6,9 @@ import sys import platform import argparse import re +import threading +import multiprocessing +from multiprocessing.pool import ThreadPool from glob import glob # Tests require at least CPython 3.3. If your default python3 executable @@ -197,13 +200,27 @@ def run_micropython(pyb, args, test_file, is_special=False): def run_feature_check(pyb, args, base_path, test_file): return run_micropython(pyb, args, base_path + "/feature_check/" + test_file, is_special=True) +class ThreadSafeCounter: + def __init__(self, start=0): + self._value = start + self._lock = threading.Lock() -def run_tests(pyb, tests, args, base_path="."): - test_count = 0 - testcase_count = 0 - passed_count = 0 - failed_tests = [] - skipped_tests = [] + def add(self, to_add): + with self._lock: self._value += to_add + + def append(self, arg): + self.add([arg]) + + @property + def value(self): + return self._value + +def run_tests(pyb, tests, args, base_path=".", num_threads=1): + test_count = ThreadSafeCounter() + testcase_count = ThreadSafeCounter() + passed_count = ThreadSafeCounter() + failed_tests = ThreadSafeCounter([]) + skipped_tests = ThreadSafeCounter([]) skip_tests = set() skip_native = False @@ -328,7 +345,7 @@ def run_tests(pyb, tests, args, base_path="."): # Remove them from the below when they work if args.emit == 'native': skip_tests.update({'basics/%s.py' % t for t in 'gen_yield_from gen_yield_from_close gen_yield_from_ducktype gen_yield_from_exc gen_yield_from_iter gen_yield_from_send gen_yield_from_stopped gen_yield_from_throw gen_yield_from_throw2 gen_yield_from_throw3 generator1 generator2 generator_args generator_close generator_closure generator_exc generator_return generator_send'.split()}) # require yield - skip_tests.update({'basics/%s.py' % t for t in 'bytes_gen class_store_class globals_del string_join'.split()}) # require yield + skip_tests.update({'basics/%s.py' % t for t in 'bytes_gen class_store_class globals_del string_join gen_stack_overflow'.split()}) # require yield skip_tests.update({'basics/async_%s.py' % t for t in 'def await await2 for for2 with with2'.split()}) # require yield skip_tests.update({'basics/%s.py' % t for t in 'try_reraise try_reraise2'.split()}) # require raise_varargs skip_tests.update({'basics/%s.py' % t for t in 'with_break with_continue with_return'.split()}) # require complete with support @@ -354,7 +371,7 @@ def run_tests(pyb, tests, args, base_path="."): skip_tests.add('micropython/heapalloc_iter.py') # requires generators skip_tests.add('micropython/schedule.py') # native code doesn't check pending events - for test_file in tests: + def run_one_test(test_file): test_file = test_file.replace('\\', '/') test_basename = os.path.basename(test_file) test_name = os.path.splitext(test_basename)[0] @@ -377,7 +394,7 @@ def run_tests(pyb, tests, args, base_path="."): if skip_it: print("skip ", test_file) skipped_tests.append(test_name) - continue + return # get expected output test_file_expected = test_file + '.exp' @@ -405,7 +422,7 @@ def run_tests(pyb, tests, args, base_path="."): output_expected = output_expected.replace(b'\r\n', b'\n') if args.write_exp: - continue + return # run MicroPython output_mupy = run_micropython(pyb, args, test_file) @@ -413,16 +430,16 @@ def run_tests(pyb, tests, args, base_path="."): if output_mupy == b'SKIP\n': print("skip ", test_file) skipped_tests.append(test_name) - continue + return - testcase_count += len(output_expected.splitlines()) + testcase_count.add(len(output_expected.splitlines())) filename_expected = test_basename + ".exp" filename_mupy = test_basename + ".out" if output_expected == output_mupy: print("pass ", test_file) - passed_count += 1 + passed_count.add(1) rm_f(filename_expected) rm_f(filename_mupy) else: @@ -437,15 +454,22 @@ def run_tests(pyb, tests, args, base_path="."): print("FAIL ", test_file) failed_tests.append(test_name) - test_count += 1 + test_count.add(1) + + if num_threads > 1: + pool = ThreadPool(num_threads) + pool.map(run_one_test, tests) + else: + for test in tests: + run_one_test(test) - print("{} tests performed ({} individual testcases)".format(test_count, testcase_count)) - print("{} tests passed".format(passed_count)) + print("{} tests performed ({} individual testcases)".format(test_count.value, testcase_count.value)) + print("{} tests passed".format(passed_count.value)) - if len(skipped_tests) > 0: - print("{} tests skipped: {}".format(len(skipped_tests), ' '.join(skipped_tests))) - if len(failed_tests) > 0: - print("{} tests failed: {}".format(len(failed_tests), ' '.join(failed_tests))) + if len(skipped_tests.value) > 0: + print("{} tests skipped: {}".format(len(skipped_tests.value), ' '.join(sorted(skipped_tests.value)))) + if len(failed_tests.value) > 0: + print("{} tests failed: {}".format(len(failed_tests.value), ' '.join(sorted(failed_tests.value)))) return False # all tests succeeded @@ -464,11 +488,14 @@ def main(): cmd_parser.add_argument('--heapsize', help='heapsize to use (use default if not specified)') cmd_parser.add_argument('--via-mpy', action='store_true', help='compile .py files to .mpy first') cmd_parser.add_argument('--keep-path', action='store_true', help='do not clear MICROPYPATH when running tests') + cmd_parser.add_argument('-j', '--jobs', default=1, metavar='N', type=int, help='Number of tests to run simultaneously') + cmd_parser.add_argument('--auto-jobs', action='store_const', dest='jobs', const=multiprocessing.cpu_count(), help='Set the -j values to the CPU (thread) count') cmd_parser.add_argument('files', nargs='*', help='input test files') args = cmd_parser.parse_args() EXTERNAL_TARGETS = ('pyboard', 'wipy', 'esp8266', 'minimal') if args.target in EXTERNAL_TARGETS: + args.jobs = 1 import pyboard pyb = pyboard.Pyboard(args.device, args.baudrate, args.user, args.password) pyb.enter_raw_repl() @@ -507,7 +534,7 @@ def main(): # run-tests script itself. base_path = os.path.dirname(sys.argv[0]) or "." try: - res = run_tests(pyb, tests, args, base_path) + res = run_tests(pyb, tests, args, base_path, args.jobs) finally: if pyb: pyb.close() diff --git a/tools/build_adafruit_bins.sh b/tools/build_adafruit_bins.sh index 0bc3d4551..34fae9d85 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 feather_m0_rfm69 feather_m0_rfm9x feather_m0_express metro_m0_express metro_m4_express pirkey_m0 trinket_m0 gemma_m0 feather52" +ATMEL_BOARDS="arduino_zero circuitplayground_express feather_m0_basic feather_m0_adalogger itsybitsy_m0_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" ROSIE_SETUPS="rosie-ci" PARALLEL="-j 5" |
